Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
P
PPSi
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
50
Issues
50
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
PPSi
Commits
efa11fb3
Commit
efa11fb3
authored
Oct 16, 2013
by
Alessandro Rubini
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'configuration'
parents
fe4470bb
7efaff34
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
626 additions
and
510 deletions
+626
-510
MAKEALL
MAKEALL
+1
-1
Makefile
Makefile
+3
-2
Makefile
arch-unix/Makefile
+1
-1
unix-startup.c
arch-unix/unix-startup.c
+12
-10
Makefile
arch-wrpc/Makefile
+3
-2
wrc_ptp_ppsi.c
arch-wrpc/wrc_ptp_ppsi.c
+0
-3
Makefile
arch-wrs/Makefile
+1
-1
wrs-startup.c
arch-wrs/wrs-startup.c
+22
-10
diag.c
diag.c
+4
-2
ppsi-manual.in
doc/ppsi-manual.in
+81
-12
ppsi-wrs.conf
etc/ppsi-wrs.conf
+20
-21
ppsi.conf
etc/ppsi.conf
+16
-24
constants.h
include/ppsi/constants.h
+1
-1
diag-macros.h
include/ppsi/diag-macros.h
+3
-26
pp-instance.h
include/ppsi/pp-instance.h
+2
-1
ppsi.h
include/ppsi/ppsi.h
+40
-3
bare-startup.c
lib-bare/bare-startup.c
+15
-3
cmdline.c
lib/cmdline.c
+126
-123
conf.c
lib/conf.c
+261
-257
hooks.c
proto-ext-whiterabbit/hooks.c
+3
-3
state-faulty.c
proto-standard/state-faulty.c
+10
-3
timeout.c
proto-standard/timeout.c
+1
-1
No files found.
MAKEALL
View file @
efa11fb3
...
...
@@ -19,7 +19,7 @@ build_diags () {
unset
USER_CFLAGS
build_one
"
$msg
, printf xint"
CONFIG_PRINTF_XINT
=
y
# then build with all diagnostics, and default printf
export
USER_CFLAGS
=
"-DVERB_LOG_MSGS
-DCONFIG_PPSI_RUNTIME_VERBOSITY
"
export
USER_CFLAGS
=
"-DVERB_LOG_MSGS"
build_one
"
$msg
, all messages"
}
...
...
Makefile
View file @
efa11fb3
...
...
@@ -9,7 +9,7 @@
ARCH
?=
unix
# Also, you can set USER_CFLAGS, like this (or on the command line)
# USER_CFLAGS = -DVERB_LOG_MSGS
-DCONFIG_PPSI_RUNTIME_VERBOSITY
# USER_CFLAGS = -DVERB_LOG_MSGS
#### In theory, users should not change stuff below this line (but please read)
...
...
@@ -73,7 +73,8 @@ export CFLAGS
# libraries: see proto-standard/Makefile as an example.
$(TARGET).o
:
$(OBJ-y)
$(LD)
-Map
$(TARGET)
.map1
-r
-o
$@
$
(
OBJ-y
)
--start-group
$(LIBS)
--end-group
$(LD)
-Map
$(TARGET)
.map1
-r
-o
$@
$
(
OBJ-y
)
$(PPSI_O_LDFLAGS)
\
--start-group
$(LIBS)
--end-group
# Finally, "make clean" is expected to work
clean
:
...
...
arch-unix/Makefile
View file @
efa11fb3
...
...
@@ -2,7 +2,7 @@
# All files are under A (short for ARCH): I'm lazy
A
:=
arch-
$(ARCH)
CFLAGS
+=
-
DCONFIG_PPSI_RUNTIME_VERBOSITY
-
Itools
CFLAGS
+=
-Itools
LIBARCH
:=
$A
/libarch.a
...
...
arch-unix/unix-startup.c
View file @
efa11fb3
...
...
@@ -22,8 +22,6 @@
#include <ppsi/ppsi.h>
#include "ppsi-unix.h"
CONST_VERBOSITY
int
pp_diag_verbosity
=
0
;
/* ppg and fields */
static
struct
pp_globals
ppg_static
;
static
DSDefault
defaultDS
;
...
...
@@ -61,8 +59,14 @@ int main(int argc, char **argv)
if
(
adjtimex
(
&
t
)
>=
0
)
timePropertiesDS
.
currentUtcOffset
=
t
.
tai
;
pp_config_file
(
ppg
,
&
argc
,
argv
,
NULL
,
"link 0
\n
iface eth0
\n
"
"proto udp
\n
"
/* mandatory trailing \n */
);
if
(
pp_parse_cmdline
(
ppg
,
argc
,
argv
)
!=
0
)
return
-
1
;
/* If no item has been parsed, provide a default file or string */
if
(
ppg
->
cfg_items
==
0
)
pp_config_file
(
ppg
,
0
,
PP_DEFAULT_CONFIGFILE
);
if
(
ppg
->
cfg_items
==
0
)
pp_config_string
(
ppg
,
strdup
(
"link 0; iface eth0; proto udp"
));
for
(
i
=
0
;
i
<
ppg
->
nlinks
;
i
++
)
{
...
...
@@ -72,12 +76,13 @@ int main(int argc, char **argv)
ppi
->
glbs
=
ppg
;
ppi
->
iface_name
=
ppi
->
cfg
.
iface_name
;
ppi
->
ethernet_mode
=
(
ppi
->
cfg
.
proto
==
0
)
?
1
:
0
;
if
(
ppi
->
cfg
.
role
==
1
)
{
/* this old-fashioned "ethernet_mode" is a single bit */
ppi
->
ethernet_mode
=
(
ppi
->
cfg
.
proto
==
PPSI_PROTO_RAW
);
if
(
ppi
->
cfg
.
role
==
PPSI_ROLE_MASTER
)
{
ppi
->
master_only
=
1
;
ppi
->
slave_only
=
0
;
}
else
if
(
ppi
->
cfg
.
role
==
2
)
{
else
if
(
ppi
->
cfg
.
role
==
PPSI_ROLE_SLAVE
)
{
ppi
->
master_only
=
0
;
ppi
->
slave_only
=
1
;
}
...
...
@@ -94,9 +99,6 @@ int main(int argc, char **argv)
exit
(
__LINE__
);
}
if
(
pp_parse_cmdline
(
ppg
,
argc
,
argv
)
!=
0
)
return
-
1
;
pp_open_globals
(
ppg
);
unix_main_loop
(
ppg
);
...
...
arch-wrpc/Makefile
View file @
efa11fb3
...
...
@@ -7,8 +7,9 @@ CFLAGS += -ffreestanding -Os \
# Root of wrpc-sw project
WRPCSW_ROOT
?=
..
CFLAGS
+=
-I
$(WRPCSW_ROOT)
/include
-I
$(WRPCSW_ROOT)
/softpll
\
-I
$(WRPCSW_ROOT)
/boards/spec
\
CFLAGS
+=
-I
$(WRPCSW_ROOT)
/include
-I
$(WRPCSW_ROOT)
/softpll
PPSI_O_LDFLAGS
=
-u
wrc_ptp_init
# FIXME ptp-noposix root; used temporarily until we clean up
PTPNOPOSIX_ROOT
=
$(WRPCSW_ROOT)
/ptp-noposix
...
...
arch-wrpc/wrc_ptp_ppsi.c
View file @
efa11fb3
...
...
@@ -27,9 +27,6 @@ extern int32_t cal_phase_transition;
int
ptp_mode
=
WRC_MODE_UNKNOWN
;
static
int
ptp_enabled
=
0
,
ptp_forced_stop
=
0
;
CONST_VERBOSITY
int
pp_diag_verbosity
=
0
;
/*ppi fields*/
static
DSDefault
defaultDS
;
static
DSCurrent
currentDS
;
...
...
arch-wrs/Makefile
View file @
efa11fb3
# All files are under A (short for ARCH): I'm lazy
A
:=
arch-
$(ARCH)
CFLAGS
+=
-
DCONFIG_PPSI_RUNTIME_VERBOSITY
-
Itools
CFLAGS
+=
-Itools
LIBARCH
:=
$A
/libarch.a
...
...
arch-wrs/wrs-startup.c
View file @
efa11fb3
...
...
@@ -26,8 +26,6 @@
#include <ppsi-wrs.h>
#include "../proto-ext-whiterabbit/wr-api.h"
CONST_VERBOSITY
int
pp_diag_verbosity
=
0
;
/* ppg and fields */
static
struct
pp_globals
ppg_static
;
static
DSDefault
defaultDS
;
...
...
@@ -90,9 +88,25 @@ int main(int argc, char **argv)
timePropertiesDS
.
currentUtcOffset
=
*
p
;
}
pp_config_file
(
ppg
,
&
argc
,
argv
,
"/wr/etc/ppsi.conf"
,
"link 0
\n
iface wr0
\n
"
/* mandatory trailing \n */
)
;
if
(
pp_parse_cmdline
(
ppg
,
argc
,
argv
)
!=
0
)
return
-
1
;
/* If no item has been parsed, provide a default file or string */
if
(
ppg
->
cfg_items
==
0
)
pp_config_file
(
ppg
,
0
,
"/wr/etc/ppsi.conf"
);
if
(
ppg
->
cfg_items
==
0
)
pp_config_file
(
ppg
,
0
,
PP_DEFAULT_CONFIGFILE
);
if
(
ppg
->
cfg_items
==
0
)
{
/* Default configuration for WR switch is all ports */
char
s
[
128
];
int
i
;
for
(
i
=
0
;
i
<
18
;
i
++
)
{
sprintf
(
s
,
"port wr%i; iface wr%i; proto raw;"
"extension whiterabbit; role auto"
,
i
,
i
);
pp_config_string
(
ppg
,
s
);
}
}
for
(
i
=
0
;
i
<
ppg
->
nlinks
;
i
++
)
{
ppi
=
&
ppg
->
pp_instances
[
i
];
...
...
@@ -101,12 +115,13 @@ int main(int argc, char **argv)
ppi
->
glbs
=
ppg
;
ppi
->
iface_name
=
ppi
->
cfg
.
iface_name
;
ppi
->
ethernet_mode
=
(
ppi
->
cfg
.
proto
==
0
)
?
1
:
0
;
if
(
ppi
->
cfg
.
role
==
1
)
{
/* this old-fashioned "ethernet_mode" is a single bit */
ppi
->
ethernet_mode
=
(
ppi
->
cfg
.
proto
==
PPSI_PROTO_RAW
);
if
(
ppi
->
cfg
.
role
==
PPSI_ROLE_MASTER
)
{
ppi
->
master_only
=
1
;
ppi
->
slave_only
=
0
;
}
else
if
(
ppi
->
cfg
.
role
==
2
)
{
else
if
(
ppi
->
cfg
.
role
==
PPSI_ROLE_SLAVE
)
{
ppi
->
master_only
=
0
;
ppi
->
slave_only
=
1
;
}
...
...
@@ -125,9 +140,6 @@ int main(int argc, char **argv)
}
if
(
pp_parse_cmdline
(
ppg
,
argc
,
argv
)
!=
0
)
return
-
1
;
pp_open_globals
(
ppg
);
wrs_main_loop
(
ppg
);
...
...
diag.c
View file @
efa11fb3
...
...
@@ -14,6 +14,7 @@ static char *thing_name[] = {
[
pp_dt_servo
]
=
"diag-servo"
,
[
pp_dt_bmc
]
=
"diag-bmc"
,
[
pp_dt_ext
]
=
"diag-extension"
,
[
pp_dt_config
]
=
"diag-config"
,
};
...
...
@@ -21,6 +22,7 @@ void __pp_diag(struct pp_instance *ppi, enum pp_diag_things th,
int
level
,
char
*
fmt
,
...)
{
va_list
args
;
char
*
name
=
ppi
?
ppi
->
iface_name
:
"ppsi"
;
if
(
!
__PP_DIAG_ALLOW
(
ppi
,
th
,
level
))
return
;
...
...
@@ -37,7 +39,7 @@ void __pp_diag(struct pp_instance *ppi, enum pp_diag_things th,
extern
int
DIAG_PUTS
(
const
char
*
s
);
pp_sprintf
(
buf
,
"%s-%i-%s: "
,
thing_name
[
th
],
level
,
ppi
->
iface_
name
);
thing_name
[
th
],
level
,
name
);
DIAG_PUTS
(
buf
);
va_start
(
args
,
fmt
);
pp_vsprintf
(
buf
,
fmt
,
args
);
...
...
@@ -46,7 +48,7 @@ void __pp_diag(struct pp_instance *ppi, enum pp_diag_things th,
}
#else
/* Use the normal output channel for diagnostics */
pp_printf
(
"%s-%i-%s: "
,
thing_name
[
th
],
level
,
ppi
->
iface_
name
);
pp_printf
(
"%s-%i-%s: "
,
thing_name
[
th
],
level
,
name
);
va_start
(
args
,
fmt
);
pp_vprintf
(
fmt
,
args
);
va_end
(
args
);
...
...
doc/ppsi-manual.in
View file @
efa11fb3
...
...
@@ -350,6 +350,51 @@ As of 2013-05 the project suffers from these known bugs:
untested in our environments.
@end itemize
@c ##########################################################################
@node Configuration
@chapter Configuration
PPSi support configuration files and individual configuration items
passed on the command line. Such support is currently not available
for freestanding architectures (the @i
{
bare
}
ones and @i
{
wrpc-sw
}
).
When PPSi starts it parses its own configuration. The command line can
include a number of @t
{
-f <file>
}
and @t
{
-C <item>
}
options; they are
processed in order, so later ones override earlier ones. A
configuration ``item'' can include several directives, using the
semicolon as a separator.
If no configuration file is specified, the program reads the default
one, which is architecture-specific (thus, the default configuration
file is processed after all the command line configuration items. The
default file name is @t
{
/etc/ppsi.conf
}
, but @t
{
arch-wrs
}
tries to
load @t
{
/wr/etc/ppsi.conf
}
first. The source tree of PPSi includes
two example configuration files in its own @t
{
etc/
}
subdirectory.
Configuration is made of of global options and port-specific options.
To configure a port, use @t
{
port <name>
}
followed by its options.
The parser allocates a new PTP state machine for each new port, but
allows changing configuration of an existing port. For instance, to
enable frame diagnostics for a specific port, you can use:
@smallexample
./ppsi -f /etc/ppsi.conf -C "port eth1; diagnostics 02"
@end smallexample
Each configuration item is made up of a keywork and an optional
argument. The argument can be either a number or a string. The
parser looks up keywords in three tables: a global table, an
architecture-specific table and an extension-specific table.
Currently not architectures or extensions provide configuration
keywords, while the list of global items is on show in @t
{
lib/conf.c
}
,
as the @t
{
pp
_
global
_
arglines
}
array. Future versions of this manual
may document the keywords, if the time allows it.
@b
{
Note:
}
most current command-line options are going to be turned into
configuration options. This applies to the priorities, intervals and
thresholds, as well as the @i
{
slave-only
}
flag.
@c ##########################################################################
@node Diagnostics
@chapter Diagnostics
...
...
@@ -357,10 +402,13 @@ As of 2013-05 the project suffers from these known bugs:
During development of PPSi, diagnostic support used several
techniques, but finally we converged on the one described here, that
is here to stay. The idea is that we need to add verbosity
per-feature and per-
link
. This fine-grained control is expected to be
per-feature and per-
port
. This fine-grained control is expected to be
important while developing features or while diagnosing problems on
new architectures.
The @t
{
diagnostics
}
configuration keyword can be used both as a global
item and as a port-specific configuration value.
@c ==========================================================================
@node Diagnostic Macros
@section Diagnostic Macros
...
...
@@ -376,18 +424,40 @@ each diagnostic thing the header defines a few bits; so we can have
diagnostic levels for each of them, but we suggest only using level 1
and 2 -- the rationale is in the header itself.
The @i
{
things
}
currently defined are: finite state machine, time code,
frame send/receive, servo, best master clock, extension-specific
features. The user is expected to pass diagnostic flags as a string,
The @i
{
things
}
currently defined are:
@itemize
@item Finite State Machine: PPSi reports FSM state transitions.
@item Time: at level 1 PPSi reports @i
{
time
_
set
}
operations
and timeouts; at level 2 it also reports @i
{
time
_
get
}
operations.
@item Frames: at level 1 PPSi reports any send and receive event; at level 2
it also shows the frame itself (using @i
{
ptpdump
}
code).
@item Servo: report servo operation. At level 2 it also shows the individual
timestamps and internal averaging.
@item BMC: at level 1 PPSi reports BMC choices, at level 2 it reports
addition of new masters as well.
@item Externsions: extension-specific information.
@item Configuration: at level 1 PPSi reports errors, at level 2 all
configuration items being parsed (from either files or command line).
@end itemize
The user is expected to pass diagnostic flags as a string,
specifying diagnostic levels for each of the things, where trailing
zeroes are optional. So for example ``@t
{
01
}
'' specifies a
diagnostic level 1 for time, and ``@t
{
102
}
'' specifies FSM at level1
diagnostic level 1 for time, and ``@t
{
102
}
'' specifies FSM at level
1
and frames at level 2. The header itself is more detailed about
the conventions.
To parse the diagnostic string, PPSi offers @i
{
pp
_
diag
_
parse
}
. The
function is used
, for example, by the code that reads the command
line
.
function is used
by both the code that reads the command line
and code that parses configuration
.
Within PPSi, developers should insert diagnostic messages by means
of the @i
{
pp
_
diag
}
function:
...
...
@@ -866,6 +936,10 @@ support since-char options; we don't want to rely on @i{getopt} which
is not available for all architectures, nor we want to implement
complex parsing.
@b
{
Note:
}
most current command
-
line options are going to be turned into
configuration options. This applies to the priorities, intervals and
thresholds, as well as the @i
{
slave
-
only
}
flag.
For standard operation, simply run @t
{
.
/
ppsi
}
with no options. It will
work like the PTPd executable, with the automatic choice of
master
/
slave defined in @sc
{
ieee
}
specification
(
announce
/
timeout mechanism
)
.
...
...
@@ -875,11 +949,6 @@ a list of the other ones please see the help message.
@table @t
@item
-
V
Increase verbosity. This is used for the @i
{
old
}
diagnostics
(
see
@ref
{
Older Diagnostics
}
)
. You may want to use it once or twice.
@item
-
d
Diagnostics. This options receives the string of diagnostic
...
...
etc/ppsi
.conf.sevensol_switch
→
etc/ppsi
-wrs.conf
View file @
efa11fb3
# ppsi configuration file for Seven Solution 18-ports switch.
# Just rename it to ppsi.conf and copy it to /etc/ppsi.conf on the
# switch.
# ppsi suggested configuration file the White Rabbit Switch
# The WRS looks for this in /wr/etc/ppsi.conf or /etc/ppsi.conf
# Global settings
clock
-
class
187
clock
-
accuracy
254
link
slave
port
slave
iface
wr0
role
slave
extension
whiterabbit
link
master1
port
master1
iface
wr1
role
auto
extension
whiterabbit
link
master2
port
master2
iface
wr2
role
auto
extension
whiterabbit
link
master3
port
master3
iface
wr3
role
auto
extension
whiterabbit
link
master4
port
master4
iface
wr4
role
auto
extension
whiterabbit
link
master5
port
master5
iface
wr5
role
auto
extension
whiterabbit
link
master6
port
master6
iface
wr6
role
auto
extension
whiterabbit
link
master7
port
master7
iface
wr7
role
auto
extension
whiterabbit
link
master8
port
master8
iface
wr8
role
auto
extension
whiterabbit
link
master9
port
master9
iface
wr9
role
auto
extension
whiterabbit
link
master10
port
master10
iface
wr10
role
auto
extension
whiterabbit
link
master11
port
master11
iface
wr11
role
auto
extension
whiterabbit
link
master12
port
master12
iface
wr12
role
auto
extension
whiterabbit
link
master13
port
master13
iface
wr13
role
auto
extension
whiterabbit
link
master14
port
master14
iface
wr14
role
auto
extension
whiterabbit
link
master15
port
master15
iface
wr15
role
auto
extension
whiterabbit
link
master16
port
master16
iface
wr16
role
auto
extension
whiterabbit
link
master17
port
master17
iface
wr17
role
auto
extension
whiterabbit
...
...
etc/ppsi.conf
View file @
efa11fb3
# Sample ppsi configuration file. Mainly to be used for multi-
link
# purposes, it defines the various
"links" for ppsi
, assigning a port
# Sample ppsi configuration file. Mainly to be used for multi-
port
# purposes, it defines the various
PTP ports
, assigning a port
# for each link and defining the link properties.
#
# Some global setting is available:
# clock-class <val>, where val is a decimal number for Clock Class
# clock-accuracy <val>, where val is a decimal number for Clock Accuracy
# See documentation or lib/conf.c for a list of parameters.
#
# Each link must be defined as follows:
# link <id>, where id is a label identifying the link (e.g. a number)
# iface <eth>, where <eth> is the interface name, e.g. eth0
# proto [raw|udp], where raw is the default
# role [auto|master|slave], where auto is the default
# extension [none|whiterabbit], where none is the default
# Both newline and semicolon act as separators. Each port is defined as:
# port <name>; iface <hwname>
# proto raw|udp (raw is the default)
# role auto|master|slave (auto is the default)
# extension none|whiterabbit (none is the default)
# Global settings
clock
-
class
248
clock
-
accuracy
254
# Link 0 is the slave, connected to the external master clock
link
0
iface
eth0
proto
raw
role
slave
extension
none
# Port 0 is slave, connected to the external master clock
port
eth
-
raw
;
iface
eth0
;
proto
raw
;
role
slave
# Link 1 is one master, driving its slave peer
link
1
iface
eth1
proto
raw
role
master
extension
none
# The same ethernet is also a udp PTP port
port
eth
-
udp
;
iface
eth0
;
proto
udp
;
role
auto
# Eth1 is master-only on raw ethernet, driving its slave peer
port
eth1
;
iface
eth1
;
proto
raw
;
role
master
# Link 2 is another master, driving another slave peer
link
2
port
eth
2
iface
eth2
proto
raw
role
master
...
...
include/ppsi/constants.h
View file @
efa11fb3
...
...
@@ -50,11 +50,11 @@ enum pp_timeouts {
PP_TO_SYNC
,
PP_TO_ANN_RECEIPT
,
PP_TO_ANN_INTERVAL
,
PP_TO_FAULTY
,
/* A few timeouts for the protocol extension */
PP_TO_EXT_0
,
PP_TO_EXT_1
,
PP_TO_EXT_2
,
PP_TO_EXT_3
,
__PP_TO_ARRAY_SIZE
,
};
...
...
include/ppsi/diag-macros.h
View file @
efa11fb3
...
...
@@ -2,32 +2,8 @@
* Macros for diagnostic prints.
*/
/*
* We still have support for compile-time settings, in order to remove
* quite a few kilobytes of stuff from the compiled binary. This first
* part of the file is the previous way, which is still used in
* several files. I plan to phase it out slowly, but let's avoid
* massive changes at this point.
*
* This verbosity argument, that can be changed at run time
* or not. If it can be changed, stuff works like this, depending on
* an integer value somewhere (it is incremented by each -V on a host run).
*
* BTW, Host build always have CONFIG_PPSI_RUNTIME_VERBOSITY set, because we
* have no size problems there (bare build don't have it, in order to
* easily test how stuff work on real freestanding environments.
*/
#ifdef CONFIG_PPSI_RUNTIME_VERBOSITY
#define CONST_VERBOSITY
/* nothing: use "int pp_diag_verbosity" */
#else
/* no runtime verbosity */
#define CONST_VERBOSITY const
/* use "const int pp_diag_verbosity */
#endif
/* CONFIG_PPSI_RUNTIME_VERBOSITY */
extern
CONST_VERBOSITY
int
pp_diag_verbosity
;
#define pp_error(...) \
if (pp_diag_verbosity) pp_printf("ERROR: " __VA_ARGS__)
#define pp_error(...) pp_printf("ERROR: " __VA_ARGS__)
/*
* The "new" diagnostics is based on flags: there are per-instance flags
...
...
@@ -56,6 +32,7 @@ enum pp_diag_things {
pp_dt_servo
=
4
,
pp_dt_bmc
=
3
,
pp_dt_ext
=
2
,
pp_dt_config
=
1
,
};
/*
* Note: we may use less bits and have more things, without changing
...
...
@@ -70,7 +47,7 @@ extern unsigned long pp_global_flags; /* Supplement ppi-specific ones */
/* So, extract the level */
#define __PP_FLAGS(ppi) (
ppi->flags
| pp_global_flags)
#define __PP_FLAGS(ppi) (
(ppi ? ppi->flags : 0)
| pp_global_flags)
#define __PP_DIAG_ALLOW(ppi, th, level) \
((__PP_FLAGS(ppi) >> (4 * (th)) & 0xf) >= level)
...
...
include/ppsi/pp-instance.h
View file @
efa11fb3
...
...
@@ -113,7 +113,7 @@ struct pp_net_path {
* (see lib/conf.c)
*/
struct
pp_instance_cfg
{
char
link
_name
[
16
];
char
port
_name
[
16
];
char
iface_name
[
16
];
int
proto
;
/* 0: raw, 1: udp */
int
role
;
/* 0: auto, 1: master, 2: slave */
...
...
@@ -207,6 +207,7 @@ struct pp_globals {
int
nlinks
;
int
max_links
;
int
cfg_items
;
/* Remember how many we parsed */
void
*
arch_data
;
/* if arch needs it */
/* FIXME Here include all is common to many interfaces */
...
...
include/ppsi/ppsi.h
View file @
efa11fb3
...
...
@@ -250,13 +250,50 @@ static inline void pp_timeout_restart_annrec(struct pp_instance *ppi)
/* The channel for an instance must be created and possibly destroyed. */
extern
int
pp_open_globals
(
struct
pp_globals
*
ppg
);
extern
int
pp_close_globals
(
struct
pp_globals
*
ppg
);
extern
int
pp_parse_cmdline
(
struct
pp_globals
*
ppg
,
int
argc
,
char
**
argv
);
extern
int
pp_config_file
(
struct
pp_globals
*
ppg
,
int
*
argcp
,
char
**
argv
,
char
*
default_name
,
char
*
default_conf
);
/*
* Configuration: we are structure-based, and a typedef simplifies things
*/
typedef
int
(
*
cfg_handler
)(
int
lineno
,
int
iarg
,
char
*
sarg
);
struct
pp_argname
{
char
*
name
;
int
value
;
};
enum
pp_argtype
{
ARG_NONE
,
ARG_INT
,
ARG_STR
,
ARG_NAMES
,
};
struct
pp_argline
{
cfg_handler
f
;
char
*
keyword
;
/* Each line starts with a keyword */
enum
pp_argtype
t
;
struct
pp_argname
*
args
;
};
/* Both the architecture and the extension can provide config arguments */
extern
struct
pp_argline
pp_arch_arglines
[];
extern
struct
pp_argline
pp_ext_arglines
[];
/* Note: config_string modifies the string it receives */
extern
int
pp_config_string
(
struct
pp_globals
*
ppg
,
char
*
s
);
extern
int
pp_config_file
(
struct
pp_globals
*
ppg
,
int
force
,
char
*
fname
);
#define PPSI_PROTO_RAW 0
#define PPSI_PROTO_UDP 1
#define PPSI_ROLE_AUTO 0
#define PPSI_ROLE_MASTER 1
#define PPSI_ROLE_SLAVE 2
#define PPSI_EXT_NONE 0
#define PPSI_EXT_WR 1
/* Servo */
extern
void
pp_servo_init
(
struct
pp_instance
*
ppi
);
...
...
lib-bare/bare-startup.c
View file @
efa11fb3
...
...
@@ -24,7 +24,6 @@ void ppsi_clear_bss(void)
static
struct
pp_globals
ppg_static
;
static
struct
pp_instance
ppi_static
;
CONST_VERBOSITY
int
pp_diag_verbosity
=
0
;
/* ppg fields */
static
DSDefault
defaultDS
;
...
...
@@ -40,8 +39,7 @@ int ppsi_main(int argc, char **argv)
struct
pp_instance
*
ppi
=
&
ppi_static
;
/* no malloc, one instance */
struct
bare_timex
t
;
if
(
pp_diag_verbosity
)
pp_printf
(
"ppsi starting. Built on %s
\n
"
,
__DATE__
);
pp_printf
(
"ppsi starting. Built on %s
\n
"
,
__DATE__
);
ppi
->
glbs
=
ppg
;
ppg
->
defaultDS
=
&
defaultDS
;
...
...
@@ -72,3 +70,17 @@ int ppsi_main(int argc, char **argv)
bare_main_loop
(
ppi
);
return
0
;
}
/* We can't parse a config file or string (no system calls, /me is lazy) */
int
pp_config_file
(
struct
pp_globals
*
ppg
,
int
force
,
char
*
fname
)
{
pp_printf
(
"No support for config file: can't read
\"
%s
\"\n
"
,
fname
);
return
-
1
;
}
int
pp_config_string
(
struct
pp_globals
*
ppg
,
char
*
s
)
{
pp_printf
(
"No support for config options: can't parse
\"
%s
\"\n
"
,
s
);
return
-
1
;
}
lib/cmdline.c
View file @
efa11fb3
...
...
@@ -5,7 +5,6 @@
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#define CONFIG_PPSI_RUNTIME_VERBOSITY 1
#include <ppsi/ppsi.h>
#define CMD_LINE_SEPARATOR {"", ""}
...
...
@@ -23,7 +22,9 @@ static struct cmd_line_opt cmd_line_list[] = {
//{"-d", "display stats"},
//{"-D", "display stats in .csv format"},
//{"-R", "record data about sync packets in a file"},
{
"-V"
,
"run in verbose mode"
},
{
"-C CONFIG_ITEM"
,
"set configuration options as stated in CONFIG_ITEM
\n\t
"
"CONFIG_ITEM must be a valid config string, enclosed by
\"
\"
"
},
{
"-f FILE"
,
"read configuration file"
},
{
"-d STRING"
,
"diagnostic level (see diag-macros.h)"
},
CMD_LINE_SEPARATOR
,
{
"-x"
,
"do not reset the clock if off by more than one second"
},
...
...
@@ -104,130 +105,132 @@ int pp_parse_cmdline(struct pp_globals *ppg, int argc, char **argv)
cmd_line_print_help
();
return
-
1
;
}
if
(
1
)
{
/* ARub: I don't want to reindent it all */
switch
(
a
[
1
])
{
case
'V'
:
pp_diag_verbosity
++
;
break
;
case
'd'
:
/* Use the general flags, per-instance TBD */
a
=
argv
[
++
i
];
pp_global_flags
=
pp_diag_parse
(
a
);
break
;
case
'x'
:
GOPTS
(
ppg
)
->
no_rst_clk
=
1
;
break
;
case
'O'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
max_rst
=
atoi
(
a
);
if
(
GOPTS
(
ppg
)
->
max_rst
>
PP_NSEC_PER_SEC
)
{
pp_printf
(
"Use -x to prevent jumps of"
switch
(
a
[
1
])
{
case
'd'
:
/* Use the general flags, per-instance TBD */
a
=
argv
[
++
i
];
pp_global_flags
=
pp_diag_parse
(
a
);
break
;
case
'C'
:
pp_config_string
(
ppg
,
argv
[
++
i
]);
break
;
case
'f'
:
pp_config_file
(
ppg
,
1
,
argv
[
++
i
]);
break
;
case
'x'
:
GOPTS
(
ppg
)
->
no_rst_clk
=
1
;
break
;
case
'O'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
max_rst
=
atoi
(
a
);
if
(
GOPTS
(
ppg
)
->
max_rst
>
PP_NSEC_PER_SEC
)
{
pp_printf
(
"Use -x to prevent jumps of"
" more than one second
\n
"
);
return
-
1
;
}
break
;
case
'M'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
max_dly
=
atoi
(
a
);
if
(
GOPTS
(
ppg
)
->
max_dly
>
PP_NSEC_PER_SEC
)
{
pp_printf
(
"Use -x to prevent jumps of"
" more than one second
\n
"
);
return
-
1
;
}
break
;
case
'M'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
max_dly
=
atoi
(
a
);
if
(
GOPTS
(
ppg
)
->
max_dly
>
PP_NSEC_PER_SEC
)
{
pp_printf
(
"Use -x to prevent jumps of"
" more than one second
\n
"
);
return
-
1
;
}
break
;
case
't'
:
GOPTS
(
ppg
)
->
no_adjust
=
1
;
break
;
case
'a'
:
a
=
argv
[
++
i
];
cmd_line_parse_two
(
a
,
&
n1
,
&
n2
);
/* no negative or zero attenuation */
if
(
n1
<
1
||
n2
<
1
)
return
-
1
;
GOPTS
(
ppg
)
->
ap
=
n1
;
GOPTS
(
ppg
)
->
ai
=
n2
;
break
;
case
'w'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
s
=
atoi
(
a
);
break
;
case
'b'
:
a
=
argv
[
++
i
];
if
(
ppg
->
nlinks
==
1
)
ppg
->
pp_instances
[
0
].
iface_name
=
a
;
else
{
/* If ppsi.conf exists and more than one link is
* configured, it makes no sense trying to set an iface
* name */
pp_printf
(
"Can not use -b option in multi-link conf"
);
return
-
1
;
}
break
;
case
'l'
:
a
=
argv
[
++
i
];
cmd_line_parse_two
(
a
,
&
n1
,
&
n2
);
GOPTS
(
ppg
)
->
inbound_latency
.
nanoseconds
=
n1
;
GOPTS
(
ppg
)
->
outbound_latency
.
nanoseconds
=
n2
;
break
;
case
'i'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
domain_number
=
atoi
(
a
);
break
;
case
'y'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
sync_intvl
=
atoi
(
a
);
break
;
case
'n'
:
a
=
argv
[
++
i
];
/* Page 237 says 0 to 4 (1s .. 16s) */
GOPTS
(
ppg
)
->
announce_intvl
=
atoi
(
a
);
if
(
GOPTS
(
ppg
)
->
announce_intvl
<
0
)
GOPTS
(
ppg
)
->
announce_intvl
=
0
;
if
(
GOPTS
(
ppg
)
->
announce_intvl
>
4
)
GOPTS
(
ppg
)
->
announce_intvl
=
4
;
break
;
case
'g'
:
/* Apply -g option globally, to each configured link */
for
(
j
=
0
;
j
<
ppg
->
nlinks
;
j
++
)
ppg
->
pp_instances
[
j
].
slave_only
=
1
;
break
;
case
'v'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
clock_quality
.
offsetScaledLogVariance
=
atoi
(
a
);
break
;
case
'r'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
clock_quality
.
clockAccuracy
=
atoi
(
a
);
break
;
case
's'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
clock_quality
.
clockClass
=
atoi
(
a
);
break
;
case
'p'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
prio1
=
atoi
(
a
);
break
;
case
'q'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
prio2
=
atoi
(
a
);
break
;
case
'h'
:
/* ignored: was "GOPTS(ppg)->e2e_mode = 1;" */
break
;
case
'e'
:
/* Apply -e option globally, to each configured link */
for
(
j
=
0
;
j
<
ppg
->
nlinks
;
j
++
)
ppg
->
pp_instances
[
j
].
ethernet_mode
=
1
;
break
;
case
'G'
:
/* gptp_mode not supported: fall through */
default:
cmd_line_print_help
();
return
-
1
;
}
break
;
case
't'
:
GOPTS
(
ppg
)
->
no_adjust
=
1
;
break
;
case
'a'
:
a
=
argv
[
++
i
];
cmd_line_parse_two
(
a
,
&
n1
,
&
n2
);
/* no negative or zero attenuation */
if
(
n1
<
1
||
n2
<
1
)
return
-
1
;
GOPTS
(
ppg
)
->
ap
=
n1
;
GOPTS
(
ppg
)
->
ai
=
n2
;
break
;
case
'w'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
s
=
atoi
(
a
);
break
;
case
'b'
:
a
=
argv
[
++
i
];
if
(
ppg
->
nlinks
==
1
)
ppg
->
pp_instances
[
0
].
iface_name
=
a
;
else
{
/* If ppsi.conf exists and more than one link is
* configured, it makes no sense trying to set an iface
* name */
pp_printf
(
"Can not use -b option in multi-link conf"
);
return
-
1
;
}
break
;
case
'l'
:
a
=
argv
[
++
i
];
cmd_line_parse_two
(
a
,
&
n1
,
&
n2
);
GOPTS
(
ppg
)
->
inbound_latency
.
nanoseconds
=
n1
;
GOPTS
(
ppg
)
->
outbound_latency
.
nanoseconds
=
n2
;
break
;
case
'i'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
domain_number
=
atoi
(
a
);
break
;
case
'y'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
sync_intvl
=
atoi
(
a
);
break
;
case
'n'
:
a
=
argv
[
++
i
];
/* Page 237 says 0 to 4 (1s .. 16s) */
GOPTS
(
ppg
)
->
announce_intvl
=
atoi
(
a
);
if
(
GOPTS
(
ppg
)
->
announce_intvl
<
0
)
GOPTS
(
ppg
)
->
announce_intvl
=
0
;
if
(
GOPTS
(
ppg
)
->
announce_intvl
>
4
)
GOPTS
(
ppg
)
->
announce_intvl
=
4
;
break
;
case
'g'
:
/* Apply -g option globally, to each configured link */
for
(
j
=
0
;
j
<
ppg
->
nlinks
;
j
++
)
ppg
->
pp_instances
[
j
].
slave_only
=
1
;
break
;
case
'v'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
clock_quality
.
offsetScaledLogVariance
=
atoi
(
a
);
break
;
case
'r'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
clock_quality
.
clockAccuracy
=
atoi
(
a
);
break
;
case
's'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
clock_quality
.
clockClass
=
atoi
(
a
);
break
;
case
'p'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
prio1
=
atoi
(
a
);
break
;
case
'q'
:
a
=
argv
[
++
i
];
GOPTS
(
ppg
)
->
prio2
=
atoi
(
a
);
break
;
case
'h'
:
/* ignored: was "GOPTS(ppg)->e2e_mode = 1;" */
break
;
case
'e'
:
/* Apply -e option globally, to each configured link */
for
(
j
=
0
;
j
<
ppg
->
nlinks
;
j
++
)
ppg
->
pp_instances
[
j
].
ethernet_mode
=
1
;
break
;
case
'G'
:
/* gptp_mode not supported: fall through */
default:
cmd_line_print_help
();
return
-
1
;
}
}
return
0
;
...
...
lib/conf.c
View file @
efa11fb3
/*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author
: Aurelio Colosimo
* Author
s: Aurelio Colosimo, Alessandro Rubini
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <ppsi/ppsi.h>
/* This file is build in hosted environments, so following headers are Ok */
/* This file is built in hosted environments, so following headers are Ok */
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
/* Each pre-defined keyword is handled in the keywords list, so that the
* same code is used to parse every token in the conf file */
/* config lines are global or ppi-specific. Keep track of globals and ppi */
static
struct
pp_globals
*
current_ppg
;
static
struct
pp_instance
*
current_ppi
;
struct
keyword_t
{
int
id
;
char
*
key
;
int
(
*
handle_key
)(
struct
pp_globals
*
ppg
,
char
*
val
);
};
enum
{
KW_INV
=
-
1
,
KW_LINK
,
KW_IFACE
,
KW_PROTO
,
KW_RAW
,
KW_UDP
,
KW_ROLE
,
KW_AUTO
,
KW_MASTER
,
KW_SLAVE
,
KW_EXT
,
KW_NONE
,
KW_WHITERAB
,
KW_CLOCK_CLASS
,
KW_CLOCK_ACCURACY
,
KW_NUMBER
};
static
int
handle_link
(
struct
pp_globals
*
ppg
,
char
*
val
);
static
int
handle_iface
(
struct
pp_globals
*
ppg
,
char
*
val
);
static
int
handle_proto
(
struct
pp_globals
*
ppg
,
char
*
val
);
static
int
handle_role
(
struct
pp_globals
*
ppg
,
char
*
val
);
static
int
handle_ext
(
struct
pp_globals
*
ppg
,
char
*
val
);
static
int
handle_clock_class
(
struct
pp_globals
*
ppg
,
char
*
val
);
static
int
handle_clock_accuracy
(
struct
pp_globals
*
ppg
,
char
*
val
);
static
struct
keyword_t
keywords
[
KW_NUMBER
]
=
{
{
KW_LINK
,
"link"
,
handle_link
},
{
KW_IFACE
,
"iface"
,
handle_iface
},
{
KW_PROTO
,
"proto"
,
handle_proto
},
{
KW_RAW
,
"raw"
},
{
KW_UDP
,
"udp"
},
{
KW_ROLE
,
"role"
,
handle_role
},
{
KW_AUTO
,
"auto"
},
{
KW_MASTER
,
"master"
},
{
KW_SLAVE
,
"slave"
},
{
KW_EXT
,
"extension"
,
handle_ext
},
{
KW_NONE
,
"none"
},
{
KW_WHITERAB
,
"whiterabbit"
},
{
KW_CLOCK_CLASS
,
"clock-class"
,
handle_clock_class
},
{
KW_CLOCK_ACCURACY
,
"clock-accuracy"
,
handle_clock_accuracy
},
};
static
int
detect_keyword
(
char
*
kw
)
/* A "port" (or "link", for compatibility) line creates or uses a pp instance */
static
int
f_port
(
int
lineno
,
int
iarg
,
char
*
sarg
)
{
int
i
;
for
(
i
=
0
;
i
<
sizeof
(
keywords
)
/
sizeof
(
keywords
[
0
]);
i
++
)
if
(
!
strcmp
(
keywords
[
i
].
key
,
kw
))
return
i
;
return
KW_INV
;
}
/* Handlers for "key" keywords: return a bool value, 1 in case of success,
* 0 otherwise */
static
int
handle_link
(
struct
pp_globals
*
ppg
,
char
*
val
)
{
/* ppg->nlinks is initialized to -1 and used as index for current link,
* so increase it before using it */
ppg
->
nlinks
++
;
if
(
ppg
->
nlinks
>=
ppg
->
max_links
)
{
pp_printf
(
"ppsi: Too many links in config file
\n
"
);
exit
(
1
);
/* First look for an existing port with the same name */
for
(
i
=
0
;
i
<
current_ppg
->
nlinks
;
i
++
)
{
current_ppi
=
current_ppg
->
pp_instances
+
i
;
if
(
!
strcmp
(
sarg
,
current_ppi
->
cfg
.
port_name
))
return
0
;
}
/* FIXME: strncpy (it is missing in bare archs by now) */
strcpy
(
ppg
->
pp_instances
[
ppg
->
nlinks
].
cfg
.
link_name
,
val
);
return
1
;
}
/* Allocate a new ppi */
if
(
current_ppg
->
nlinks
>=
current_ppg
->
max_links
)
{
pp_printf
(
"config line %i: out of available ports
\n
"
,
lineno
);
return
-
1
;
}
current_ppi
=
current_ppg
->
pp_instances
+
current_ppg
->
nlinks
;
static
int
handle_iface
(
struct
pp_globals
*
ppg
,
char
*
val
)
{
/* FIXME: strncpy (it is missing in bare archs by now) */
strcpy
(
ppg
->
pp_instances
[
ppg
->
nlinks
].
iface_name
,
val
);
return
1
;
strcpy
(
current_ppi
->
cfg
.
port_name
,
sarg
);
current_ppg
->
nlinks
++
;
return
0
;
}
static
int
handle_clock_class
(
struct
pp_globals
*
ppg
,
char
*
val
)
#define CHECK_PPI(need)
/* Quick hack to factorize errors later */
\
({if (need && !current_ppi) { \
pp_printf("config line %i: no port for this config\n", lineno);\
return -1; \
} \
if (!need && current_ppi) { \
pp_printf("config line %i: global config under \"port\"\n", \
lineno); \
return -1; \
}})
static
int
f_if
(
int
lineno
,
int
iarg
,
char
*
sarg
)
{
GOPTS
(
ppg
)
->
clock_quality
.
clockClass
=
atoi
(
val
);
return
1
;
CHECK_PPI
(
1
);
strcpy
(
current_ppi
->
cfg
.
iface_name
,
sarg
);
return
0
;
}
static
int
handle_clock_accuracy
(
struct
pp_globals
*
ppg
,
char
*
val
)
/* The following ones are so similar. Bah... set a pointer somewhere? */
static
int
f_proto
(
int
lineno
,
int
iarg
,
char
*
sarg
)
{
GOPTS
(
ppg
)
->
clock_quality
.
clockAccuracy
=
atoi
(
val
);
return
1
;
CHECK_PPI
(
1
);
current_ppi
->
cfg
.
proto
=
iarg
;
return
0
;
}
static
int
handle_proto
(
struct
pp_globals
*
ppg
,
char
*
val
)
static
int
f_role
(
int
lineno
,
int
iarg
,
char
*
sarg
)
{
int
v_id
;
v_id
=
detect_keyword
(
val
);
switch
(
v_id
)
{
case
KW_RAW
:
case
KW_UDP
:
ppg
->
pp_instances
[
ppg
->
nlinks
].
cfg
.
proto
=
v_id
-
KW_RAW
;
break
;
default:
return
0
;
}
return
1
;
CHECK_PPI
(
1
);
current_ppi
->
cfg
.
role
=
iarg
;
return
0
;
}
static
int
handle_role
(
struct
pp_globals
*
ppg
,
char
*
val
)
static
int
f_ext
(
int
lineno
,
int
iarg
,
char
*
sarg
)
{
int
v_id
;
v_id
=
detect_keyword
(
val
);
switch
(
v_id
)
{
case
KW_AUTO
:
case
KW_MASTER
:
case
KW_SLAVE
:
ppg
->
pp_instances
[
ppg
->
nlinks
].
cfg
.
role
=
v_id
-
KW_AUTO
;
break
;
default:
return
0
;
}
return
1
;
CHECK_PPI
(
1
);
current_ppi
->
cfg
.
ext
=
iarg
;
return
0
;
}
static
int
handle_ext
(
struct
pp_globals
*
ppg
,
char
*
val
)
/* The following two are identical as well. I really need a pointer... */
static
int
f_class
(
int
lineno
,
int
iarg
,
char
*
sarg
)
{
int
v_id
;
v_id
=
detect_keyword
(
val
);
switch
(
v_id
)
{
case
KW_NONE
:
case
KW_WHITERAB
:
ppg
->
pp_instances
[
ppg
->
nlinks
].
cfg
.
ext
=
v_id
-
KW_NONE
;
break
;
default:
return
0
;
}
return
1
;
CHECK_PPI
(
0
);
GOPTS
(
current_ppg
)
->
clock_quality
.
clockClass
=
iarg
;
return
0
;
}
/* Called with the pair key-val detected by pp_parse_conf state machine */
static
int
handle_key_val
(
struct
pp_globals
*
ppg
,
char
*
key
,
char
*
val
)
static
int
f_accuracy
(
int
lineno
,
int
iarg
,
char
*
sarg
)
{
int
k_id
;
k_id
=
detect_keyword
(
key
);
switch
(
k_id
)
{
case
KW_LINK
:
case
KW_IFACE
:
case
KW_PROTO
:
case
KW_ROLE
:
case
KW_EXT
:
case
KW_CLOCK_CLASS
:
case
KW_CLOCK_ACCURACY
:
return
keywords
[
k_id
].
handle_key
(
ppg
,
val
);
default:
return
0
;
}
CHECK_PPI
(
0
);
GOPTS
(
current_ppg
)
->
clock_quality
.
clockAccuracy
=
iarg
;
return
0
;
}
/*
Parse configuration (e.g. coming from /etc/ppsi.conf file)
*/
static
int
pp_parse_conf
(
struct
pp_globals
*
ppg
,
char
*
conf
,
int
len
)
/*
Diagnostics can be per-port or global
*/
static
int
f_diag
(
int
lineno
,
int
iarg
,
char
*
sarg
)
{
int
st
=
0
;
char
c
;
char
key
[
16
],
val
[
16
];
int
toklen
=
0
;
int
ln
=
1
;
/* Line counter */
int
newln
;
int
i
;
unsigned
long
level
=
pp_diag_parse
(
sarg
);
/* ppg->nlinks is initialized to -1 and increased at first link found,
* so that we can use it as array index */
ppg
->
nlinks
=
-
1
;
if
(
current_ppi
)
current_ppi
->
flags
=
level
;
else
pp_global_flags
=
level
;
return
0
;
}
for
(
i
=
0
;
i
<
len
;
i
++
)
{
c
=
conf
[
i
];
/* These are the tables for the parser */
static
struct
pp_argname
arg_proto
[]
=
{
{
"raw"
,
PPSI_PROTO_RAW
},
{
"udp"
,
PPSI_PROTO_UDP
},
{},
};
static
struct
pp_argname
arg_role
[]
=
{
{
"auto"
,
PPSI_ROLE_AUTO
},
{
"master"
,
PPSI_ROLE_MASTER
},
{
"slave"
,
PPSI_ROLE_SLAVE
},
{},
};
static
struct
pp_argname
arg_ext
[]
=
{
{
"none"
,
PPSI_EXT_NONE
},
{
"whiterabbit"
,
PPSI_EXT_WR
},
{},
};
/* Increase line counter and check if latest line is invalid */
newln
=
0
;
if
((
c
==
'\n'
)
||
(
c
==
'\0'
))
{
ln
++
;
newln
=
1
;
if
(
st
==
2
)
goto
ret_invalid_line
;
}
static
struct
pp_argline
pp_global_arglines
[]
=
{
{
f_port
,
"port"
,
ARG_STR
},
{
f_port
,
"link"
,
ARG_STR
},
/* old name for "port" */
{
f_if
,
"iface"
,
ARG_STR
},
{
f_proto
,
"proto"
,
ARG_NAMES
,
arg_proto
},
{
f_role
,
"role"
,
ARG_NAMES
,
arg_role
},
{
f_ext
,
"extension"
,
ARG_NAMES
,
arg_ext
},
{
f_diag
,
"diagnostics"
,
ARG_STR
},
{
f_class
,
"clock-class"
,
ARG_INT
},
{
f_accuracy
,
"clock-accuracy"
,
ARG_INT
},
{}
};
switch
(
st
)
{
case
0
:
/* initial status */
if
((
c
==
' '
)
||
(
c
==
'\t'
)
||
(
c
==
'\r'
)
||
(
newln
))
continue
;
if
(
c
==
'#'
)
st
=
1
;
else
{
key
[
0
]
=
c
;
toklen
=
1
;
st
=
2
;
}
break
;
/* Provide default empty argument lines for architecture and extension */
struct
pp_argline
pp_arch_arglines
[]
__attribute__
((
weak
))
=
{
{}
};
struct
pp_argline
pp_ext_arglines
[]
__attribute__
((
weak
))
=
{
{}
};
case
1
:
/* ignoring commented line, those starting with '#' */
if
(
newln
)
st
=
0
;
else
continue
;
break
;
/* local implementation of isblank() for bare-metal users */
static
int
blank
(
int
c
)
{
return
c
==
' '
||
c
==
'\t'
||
c
==
'\n'
;
}
case
2
:
/* detecting key */
static
char
*
first_word
(
char
*
line
,
char
**
rest
)
{
char
*
ret
;
int
l
=
strlen
(
line
)
-
1
;
/* remove trailing blanks */
while
(
l
>=
0
&&
blank
(
line
[
l
]))
line
[
l
--
]
=
'\0'
;
/* skip leading blanks to find first word */
while
(
*
line
&&
blank
(
*
line
))
line
++
;
ret
=
line
;
/* find next blank and thim there*/
while
(
*
line
&&
!
blank
(
*
line
))
line
++
;
if
(
*
line
)
{
*
line
=
'\0'
;
line
++
;
}
*
rest
=
line
;
return
ret
;
}
if
(
toklen
==
sizeof
(
key
))
goto
ret_invalid_line
;
static
int
pp_config_line
(
struct
pp_globals
*
ppg
,
char
*
line
,
int
lineno
)
{
struct
pp_argline
*
l
;
struct
pp_argname
*
n
;
char
*
word
;
int
i
;
if
((
c
!=
' '
)
&&
(
c
!=
'\t'
))
key
[
toklen
++
]
=
c
;
else
{
st
=
3
;
key
[
toklen
]
=
'\0'
;
toklen
=
0
;
}
current_ppg
=
ppg
;
pp_diag
(
NULL
,
config
,
2
,
"parsing line %i:
\"
%s
\"\n
"
,
lineno
,
line
);
word
=
first_word
(
line
,
&
line
);
/* now line points to the next word, with no leading blanks */
if
(
word
[
0
]
==
'#'
)
return
0
;
if
(
!*
word
)
{
/* empty or blank-only */
current_ppi
=
NULL
;
return
0
;
}
/* Look for the configuration keyword in global, arch, ext */
for
(
l
=
pp_global_arglines
;
l
->
f
;
l
++
)
if
(
!
strcmp
(
word
,
l
->
keyword
))
break
;
if
(
!
l
->
f
)
for
(
l
=
pp_arch_arglines
;
l
->
f
;
l
++
)
if
(
!
strcmp
(
word
,
l
->
keyword
))
break
;
if
(
!
l
->
f
)
for
(
l
=
pp_ext_arglines
;
l
->
f
;
l
++
)
if
(
!
strcmp
(
word
,
l
->
keyword
))
break
;
if
(
!
l
->
f
)
{
pp_diag
(
NULL
,
config
,
1
,
"line %i: no such keyword
\"
%s
\"\n
"
,
lineno
,
word
);
return
-
1
;
}
case
3
:
/* detecting val */
switch
(
l
->
t
)
{
if
(
toklen
==
sizeof
(
val
))
goto
ret_invalid_line
;
case
ARG_NONE
:
break
;
if
((
c
!=
' '
)
&&
(
c
!=
'\t'
)
&&
(
c
!=
'\r'
)
&&
(
!
newln
))
val
[
toklen
++
]
=
c
;
else
if
(
newln
)
{
val
[
toklen
]
=
'\0'
;
if
(
!
handle_key_val
(
ppg
,
key
,
val
))
goto
ret_invalid_line
;
st
=
0
;
toklen
=
0
;
}
case
ARG_INT
:
if
(
sscanf
(
line
,
"%i"
,
&
i
)
!=
1
)
{
pp_diag
(
NULL
,
config
,
1
,
"line %i:
\"
%s
\"
: not int
\n
"
,
lineno
,
word
);
return
-
1
;
}
if
(
l
->
f
(
lineno
,
i
,
NULL
))
return
-
1
;
break
;
case
ARG_STR
:
while
(
*
line
&&
*
line
==
' '
&&
*
line
==
'\t'
)
line
++
;
if
(
l
->
f
(
lineno
,
0
,
line
))
return
-
1
;
break
;
case
ARG_NAMES
:
for
(
n
=
l
->
args
;
n
->
name
;
n
++
)
if
(
!
strcmp
(
line
,
n
->
name
))
break
;
if
(
!
n
->
name
)
{
pp_diag
(
NULL
,
config
,
1
,
"line %i: wrong arg
\"
%s
\"
"
" for
\"
%s
\"\n
"
,
lineno
,
line
,
word
);
return
-
1
;
}
if
(
l
->
f
(
lineno
,
n
->
value
,
NULL
))
return
-
1
;
break
;
}
/* finally, increase nlinks so that it is equal to the configured links
* count */
ppg
->
nlinks
++
;
return
0
;
ret_invalid_line:
ln
--
;
return
-
ln
;
}
/* Parse a whole string by splitting lines at '\n' or ';' */
static
int
pp_parse_conf
(
struct
pp_globals
*
ppg
,
char
*
conf
,
int
len
)
{
int
errcount
=
0
;
char
*
line
,
*
rest
,
term
;
int
lineno
=
1
;
line
=
conf
;
do
{
for
(
rest
=
line
;
*
rest
&&
*
rest
!=
'\n'
&&
*
rest
!=
';'
;
rest
++
)
;
term
=
*
rest
;
*
rest
=
'\0'
;
if
(
*
line
)
errcount
+=
pp_config_line
(
ppg
,
line
,
lineno
)
<
0
;
line
=
rest
+
1
;
if
(
term
==
'\n'
)
lineno
++
;
}
while
(
term
);
/* if terminator was already 0, we are done */
pp_config_line
(
ppg
,
""
,
0
);
/* done: clear current_ppi */
return
errcount
?
-
1
:
0
;
}
/* Open a
bout a
file, warn if not found */
static
int
pp_open_conf_file
(
char
*
*
argv
,
char
*
name
)
/* Open a file, warn if not found */
static
int
pp_open_conf_file
(
char
*
name
)
{
int
fd
;
...
...
@@ -267,77 +289,59 @@ static int pp_open_conf_file(char **argv, char *name)
return
-
1
;
fd
=
open
(
name
,
O_RDONLY
);
if
(
fd
>=
0
)
{
pp_printf
(
"
%s: Using config file %s
\n
"
,
argv
[
0
]
,
name
);
pp_printf
(
"
Using config file %s
\n
"
,
name
);
return
fd
;
}
pp_printf
(
"%s: Warning: %s: %s
\n
"
,
argv
[
0
],
name
,
strerror
(
errno
));
pp_printf
(
"Warning: %s: %s
\n
"
,
name
,
strerror
(
errno
));
return
-
1
;
}
/*
* This is the public entry point, that is passed both a default name
* and a default value for the configuration file. This only builds
* in hosted environment.
* This is one of the public entry points, opening a file
*
* The function allows "-f <config>" to appear on the command line,
* and modifies the command line accordingly (hackish, I admit)
* "force" means that the called wants to open *this file.
* In this case we count it even if it fails, so the default
* config file is not used
*/
int
pp_config_file
(
struct
pp_globals
*
ppg
,
int
*
argcp
,
char
**
argv
,
char
*
default_name
,
char
*
default_conf
)
int
pp_config_file
(
struct
pp_globals
*
ppg
,
int
force
,
char
*
fname
)
{
char
*
name
=
NULL
;
int
conf_fd
,
i
,
conf_len
=
0
;
int
r
=
0
,
next_r
;
struct
stat
conf_fs
;
char
*
conf_buf
;
/* First, look for fname on the command line (which is parsed later) */
for
(
i
=
1
;
i
<
*
argcp
-
1
;
i
++
)
{
if
(
strcmp
(
argv
[
i
],
"-f"
))
continue
;
/* found: remove it from argv */
name
=
argv
[
i
+
1
];
for
(;
i
<
*
argcp
-
2
;
i
++
)
argv
[
i
]
=
argv
[
i
+
2
];
*
argcp
-=
2
;
conf_fd
=
pp_open_conf_file
(
fname
);
if
(
conf_fd
<
0
)
{
if
(
force
)
ppg
->
cfg_items
++
;
return
-
1
;
}
conf_fd
=
pp_open_conf_file
(
argv
,
name
);
/* Then try the caller-provided name */
if
(
conf_fd
<
0
)
conf_fd
=
pp_open_conf_file
(
argv
,
default_name
);
/* Finally, the project-wide name */
if
(
conf_fd
<
0
)
conf_fd
=
pp_open_conf_file
(
argv
,
PP_DEFAULT_CONFIGFILE
);
/* If nothing, use provided string */
if
(
conf_fd
<
0
)
{
/* Read it, if any */
conf_buf
=
strdup
(
default_conf
);
conf_len
=
strlen
(
conf_buf
)
-
1
;
}
else
{
int
r
=
0
,
next_r
;
fstat
(
conf_fd
,
&
conf_fs
);
conf_buf
=
calloc
(
1
,
conf_fs
.
st_size
+
2
);
do
{
next_r
=
conf_fs
.
st_size
-
conf_len
;
r
=
read
(
conf_fd
,
&
conf_buf
[
conf_len
],
next_r
);
if
(
r
<=
0
)
break
;
conf_len
=
strlen
(
conf_buf
);
}
while
(
conf_len
<
conf_fs
.
st_size
);
ppg
->
cfg_items
++
;
close
(
conf_fd
);
}
/* read the whole file, it is split up later on */
/* We need this trailing \n for the parser */
conf_buf
[
conf_len
+
1
]
=
'\n'
;
fstat
(
conf_fd
,
&
conf_fs
);
conf_buf
=
calloc
(
1
,
conf_fs
.
st_size
+
2
)
;
if
((
i
=
pp_parse_conf
(
ppg
,
conf_buf
,
conf_len
))
<
0
)
{
pp_printf
(
"%s: configuration: error at line %d
\n
"
,
argv
[
0
],
-
1
);
exit
(
1
);
}
do
{
next_r
=
conf_fs
.
st_size
-
conf_len
;
r
=
read
(
conf_fd
,
&
conf_buf
[
conf_len
],
next_r
);
if
(
r
<=
0
)
break
;
conf_len
=
strlen
(
conf_buf
);
}
while
(
conf_len
<
conf_fs
.
st_size
);
close
(
conf_fd
);
i
=
pp_parse_conf
(
ppg
,
conf_buf
,
conf_len
);
free
(
conf_buf
);
return
0
;
return
i
;
}
/*
* This is the other public entry points, opening a file
*/
int
pp_config_string
(
struct
pp_globals
*
ppg
,
char
*
s
)
{
return
pp_parse_conf
(
ppg
,
s
,
strlen
(
s
));
}
proto-ext-whiterabbit/hooks.c
View file @
efa11fb3
...
...
@@ -37,12 +37,12 @@ static int wr_open(struct pp_globals *ppg, struct pp_runtime_opts *rt_opts)
* wr_data. May I move it to pp_globals? */
ppg
->
pp_instances
[
i
].
ext_data
=
&
wr_data
;
if
(
ppi
->
cfg
.
ext
)
{
if
(
ppi
->
cfg
.
ext
==
PPSI_EXT_WR
)
{
switch
(
ppi
->
cfg
.
role
)
{
case
1
:
case
PPSI_ROLE_MASTER
:
WR_DSPOR
(
ppi
)
->
wrConfig
=
WR_M_ONLY
;
break
;
case
2
:
case
PPSI_ROLE_SLAVE
:
WR_DSPOR
(
ppi
)
->
wrConfig
=
WR_S_ONLY
;
break
;
default:
...
...
proto-standard/state-faulty.c
View file @
efa11fb3
...
...
@@ -10,12 +10,19 @@
/*
* Fault troubleshooting. Now only prints an error messages and comes back to
* PTP_INITIALIZING state
* PTP_INITIALIZING state
after a 4-seconds grace period
*/
int
pp_faulty
(
struct
pp_instance
*
ppi
,
unsigned
char
*
pkt
,
int
plen
)
{
pp_diag
(
ppi
,
fsm
,
1
,
"Faulty state detected
\n
"
);
ppi
->
next_state
=
PPS_INITIALIZING
;
if
(
ppi
->
is_new_state
)
{
pp_timeout_set
(
ppi
,
PP_TO_FAULTY
,
4000
);
}
if
(
pp_timeout
(
ppi
,
PP_TO_FAULTY
))
{
ppi
->
next_state
=
PPS_INITIALIZING
;
return
0
;
}
ppi
->
next_delay
=
pp_ms_to_timeout
(
ppi
,
PP_TO_FAULTY
);
return
0
;
}
proto-standard/timeout.c
View file @
efa11fb3
...
...
@@ -13,10 +13,10 @@ static char *timeout_names[__PP_TO_ARRAY_SIZE] __attribute__((used)) = {
N
(
PP_TO_SYNC
),
N
(
PP_TO_ANN_RECEIPT
),
N
(
PP_TO_ANN_INTERVAL
),
N
(
PP_TO_FAULTY
),
N
(
PP_TO_EXT_0
),
N
(
PP_TO_EXT_1
),
N
(
PP_TO_EXT_2
),
N
(
PP_TO_EXT_3
),
};
/*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment