Commit 0c74aa23 authored by Alessandro Rubini's avatar Alessandro Rubini

Merge branch 'ptpdump-within-ppsi'

This includes the functionality of tools/ptpdump inside the ppsi
executable. Each net_ops->send and net_ops->recv must call the
dumping functions (gnu-linux and bare-* already to in this branch;
arch-wrpc does not, and I'll all it later).
parents b31bb242 1c729a8c
# Alessandro Rubini for CERN, 2011 -- public domain
CFLAGS += -ffreestanding -Os -fno-stack-protector
CFLAGS += -ffreestanding -Os -fno-stack-protector -Itools
ARCH_LDFLAGS = -nostdlib -static -T $(ARCH).lds
# All files are under A (short for ARCH) or L (short for lib): I'm lazy
......@@ -18,6 +18,7 @@ OBJ-libarch := $L/bare-startup.o \
$L/bare-time.o \
$A/syscalls.o \
lib/libc-functions.o \
lib/dump-funcs.o \
lib/cmdline.o \
lib/div64.o
......
# Alessandro Rubini for CERN, 2011 -- public domain
CFLAGS += -ffreestanding -Os -fno-stack-protector
CFLAGS += -ffreestanding -Os -fno-stack-protector -Itools
ARCH_LDFLAGS = -nostdlib -static -T $(ARCH).lds
# All files are under A (short for ARCH) or L (short for lib): I'm lazy
......@@ -19,6 +19,7 @@ OBJ-libarch := $L/bare-startup.o \
$A/syscall.o \
$A/syscalls.o \
lib/libc-functions.o \
lib/dump-funcs.o \
lib/cmdline.o \
lib/div64.o
......
......@@ -3,7 +3,7 @@
# All files are under A (short for ARCH): I'm lazy
A := arch-$(ARCH)
CFLAGS += -DCONFIG_PPSI_RUNTIME_VERBOSITY
CFLAGS += -DCONFIG_PPSI_RUNTIME_VERBOSITY -Itools
LIBARCH := $A/libarch.a
......@@ -15,6 +15,7 @@ OBJ-libarch := $A/posix-startup.o \
$A/posix-time.o \
lib/cmdline.o \
lib/libc-functions.o \
lib/dump-funcs.o \
lib/div64.o
$(LIBARCH): $(OBJ-libarch)
......
......@@ -17,6 +17,7 @@
#include <arpa/inet.h>
#include <ppsi/ppsi.h>
#include "ptpdump.h"
#include "posix.h"
/* posix_recv_msg uses recvmsg for timestamp query */
......@@ -93,11 +94,15 @@ static int posix_net_recv(struct pp_instance *ppi, void *pkt, int len,
TimeInternal *t)
{
struct pp_channel *ch1, *ch2;
int ret;
if (OPTS(ppi)->ethernet_mode) {
int fd = NP(ppi)->ch[PP_NP_GEN].fd;
return posix_recv_msg(ppi, fd, pkt, len, t);
ret = posix_recv_msg(ppi, fd, pkt, len, t);
if (ret > 0 && pp_diag_allow(ppi, frames, 2))
dump_1588pkt("recv: ", pkt, ret, t);
return ret;
}
/* else: UDP, we can return one frame only, so swap priority */
......@@ -111,13 +116,15 @@ static int posix_net_recv(struct pp_instance *ppi, void *pkt, int len,
POSIX_ARCH(ppi)->rcv_switch = !POSIX_ARCH(ppi)->rcv_switch;
ret = -1;
if (ch1->pkt_present)
return posix_recv_msg(ppi, ch1->fd, pkt, len, t);
if (ch2->pkt_present)
return posix_recv_msg(ppi, ch2->fd, pkt, len, t);
ret = posix_recv_msg(ppi, ch1->fd, pkt, len, t);
else if (ch2->pkt_present)
ret = posix_recv_msg(ppi, ch2->fd, pkt, len, t);
return -1;
if (ret > 0 && pp_diag_allow(ppi, frames, 2))
dump_payloadpkt("recv: ", pkt, ret, t);
return ret;
}
static int posix_net_send(struct pp_instance *ppi, void *pkt, int len,
......@@ -125,6 +132,7 @@ static int posix_net_send(struct pp_instance *ppi, void *pkt, int len,
{
struct sockaddr_in addr;
struct ethhdr *hdr = pkt;
int ret;
if (OPTS(ppi)->ethernet_mode) {
hdr->h_proto = htons(ETH_P_1588);
......@@ -136,7 +144,10 @@ static int posix_net_send(struct pp_instance *ppi, void *pkt, int len,
if (t)
ppi->t_ops->get(ppi, t);
return send(NP(ppi)->ch[PP_NP_GEN].fd, hdr, len, 0);
ret = send(NP(ppi)->ch[PP_NP_GEN].fd, hdr, len, 0);
if (pp_diag_allow(ppi, frames, 2))
dump_1588pkt("send: ", pkt, len, t);
return ret;
}
/* else: UDP */
......@@ -148,10 +159,11 @@ static int posix_net_send(struct pp_instance *ppi, void *pkt, int len,
if (t)
ppi->t_ops->get(ppi, t);
return sendto(NP(ppi)->ch[chtype].fd, pkt, len, 0,
ret = sendto(NP(ppi)->ch[chtype].fd, pkt, len, 0,
(struct sockaddr *)&addr, sizeof(struct sockaddr_in));
return -1;
if (pp_diag_allow(ppi, frames, 2))
dump_payloadpkt("send: ", pkt, len, t);
return ret;
}
/* To open a channel we must bind to an interface and so on */
......
......@@ -3,6 +3,7 @@
CFLAGS += -ffreestanding -Os \
-ffunction-sections -fdata-sections \
-mmultiply-enabled -mbarrel-shift-enabled \
-Itools
ARCH_LDFLAGS = -nostdlib -static -T $(ARCH).lds
......@@ -31,6 +32,7 @@ OBJ-libarch := $A/wrpc-socket.o \
$A/wrpc-io.o \
$A/wrpc-spll.o \
$A/wrpc-calibration.o \
lib/dump-funcs.o \
lib/div64.o
$(LIBARCH): $(OBJ-libarch)
......
......@@ -16,7 +16,7 @@ static void pp_fsm_printf(struct pp_instance *ppi, char *fmt, ...)
TimeInternal t;
unsigned long oflags = pp_global_flags;
if (!__PP_DIAG_ALLOW(ppi, pp_dt_fsm, 1))
if (!pp_diag_allow(ppi, fsm, 1))
return;
/* temporarily set NOTIMELOG, as we'll print the time ourselves */
......@@ -87,7 +87,7 @@ int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen)
*/
if (plen) {
if (plen >= PP_HEADER_LENGTH)
err = msg_unpack_header(ppi, packet);
err = msg_unpack_header(ppi, packet, plen);
else
err = 1;
if (err) {
......
......@@ -128,6 +128,9 @@ extern void __pp_diag(struct pp_instance *ppi, enum pp_diag_things th,
PP_HAS_DIAG; /* return 1 if done, 0 if not done */ \
})
#define pp_diag_allow(ppi_, th_, level_) \
(PP_HAS_DIAG && __PP_DIAG_ALLOW(ppi_, pp_dt_ ## th_, level_))
/*
* And this is the parser of the string. Internally it obeys VERB_LOG_MESGS
* to set the value to 0xfffffff0 to be compatible with previous usage.
......
......@@ -241,7 +241,7 @@ extern int bmc(struct pp_instance *ppi);
/* msg.c */
extern void msg_pack_header(struct pp_instance *ppi, void *buf);
extern int __attribute__((warn_unused_result))
msg_unpack_header(struct pp_instance *ppi, void *buf);
msg_unpack_header(struct pp_instance *ppi, void *buf, int plen);
void *msg_copy_header(MsgHeader *dest, MsgHeader *src);
extern void msg_pack_sync(struct pp_instance *ppi, Timestamp *orig_tstamp);
extern void msg_unpack_sync(void *buf, MsgSync *sync);
......
......@@ -4,22 +4,28 @@
/* Socket interface for bare Linux */
#include <ppsi/ppsi.h>
#include "ptpdump.h"
#include "bare-linux.h"
/* FIXME: which socket we receive and send with? */
static int bare_net_recv(struct pp_instance *ppi, void *pkt, int len,
TimeInternal *t)
{
int ret;
if (t)
ppi->t_ops->get(ppi, t);
return sys_recv(NP(ppi)->ch[PP_NP_GEN].fd, pkt, len, 0);
ret = sys_recv(NP(ppi)->ch[PP_NP_GEN].fd, pkt, len, 0);
if (ret > 0 && pp_diag_allow(ppi, frames, 2))
dump_1588pkt("recv: ", pkt, ret, t);
return ret;
}
static int bare_net_send(struct pp_instance *ppi, void *pkt, int len,
TimeInternal *t, int chtype, int use_pdelay_addr)
{
struct bare_ethhdr *hdr = pkt;
int ret;
hdr->h_proto = htons(ETH_P_1588);
......@@ -31,7 +37,10 @@ static int bare_net_send(struct pp_instance *ppi, void *pkt, int len,
if (t)
ppi->t_ops->get(ppi, t);
return sys_send(NP(ppi)->ch[chtype].fd, pkt, len, 0);
ret = sys_send(NP(ppi)->ch[chtype].fd, pkt, len, 0);
if (ret > 0 && pp_diag_allow(ppi, frames, 2))
dump_1588pkt("send: ", pkt, len, t);
return ret;
}
#define SHUT_RD 0
......
../tools/dump-funcs.c
\ No newline at end of file
/*
* This header is a hack, meant to provide data structures for
* tools/dump-funcs.c when it is built in a freestanding environment.
*/
#include <arch/arch.h> /* for ntohs and ntohl */
/* From: /usr/include/linux/if_ether.h with s/__be16/uint16_t/ */
#define ETH_ALEN 6 /* Octets in one ethernet addr */
#define ETH_HLEN 14 /* Total octets in header. */
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
uint16_t h_proto; /* packet type ID field */
} __attribute__((packed));
/* From: /usr/include/netinet/ip.h, renaming the bitfield to avoid using them */
struct iphdr {
unsigned int ihl_unused:4;
unsigned int version_unused:4;
uint8_t tos;
uint16_t tot_len;
uint16_t id;
uint16_t frag_off;
uint8_t ttl;
uint8_t protocol;
uint16_t check;
uint32_t saddr;
uint32_t daddr;
/*The options start here. */
};
/* From: /usr/include/netinet/udp.h */
struct udphdr {
uint16_t source;
uint16_t dest;
uint16_t len;
uint16_t check;
};
......@@ -6,89 +6,8 @@
#include <ppsi/ppsi.h>
#include "common-fun.h"
/*
* Temporarily, use the diagnostic level to set a fake pp_verbose_dump.
* We can't use ppi-specific flags at this point, but I plan to fix
* this msg.c overall -- ARub
*/
#define pp_verbose_dump \
__PP_DIAG_ALLOW_FLAGS(pp_global_flags, pp_dt_frames, 2)
static void Integer64_display(const char *label, Integer64 *bigint)
{
if (pp_verbose_dump) {
pp_Vprintf("%s:\n", label);
pp_Vprintf("LSB: %u\n", bigint->lsb);
pp_Vprintf("MSB: %d\n", bigint->msb);
}
}
static void UInteger48_display(const char *label, UInteger48 *bigint)
{
if (pp_verbose_dump) {
pp_Vprintf("%s:\n", label);
pp_Vprintf("LSB: %u\n", bigint->lsb);
pp_Vprintf("MSB: %u\n", bigint->msb);
}
}
static void timestamp_display(const char *label, Timestamp *timestamp)
{
if (pp_verbose_dump) {
pp_Vprintf("%s:\n", label);
UInteger48_display("seconds", &timestamp->secondsField);
pp_Vprintf("nanoseconds: %u\n", timestamp->nanosecondsField);
}
}
static void msg_display_header(MsgHeader *header)
{
if (pp_verbose_dump) {
pp_Vprintf("Message header:\n");
pp_Vprintf("\n");
pp_Vprintf("transportSpecific: %d\n",
header->transportSpecific);
pp_Vprintf("messageType: %d\n", header->messageType);
pp_Vprintf("versionPTP: %d\n", header->versionPTP);
pp_Vprintf("messageLength: %d\n", header->messageLength);
pp_Vprintf("domainNumber: %d\n", header->domainNumber);
pp_Vprintf("FlagField %02x:%02x\n", header->flagField[0],
header->flagField[1]);
Integer64_display("correctionfield", &header->correctionfield);
/* FIXME diag portIdentity_display(&h->sourcePortIdentity); */
pp_Vprintf("sequenceId: %d\n", header->sequenceId);
pp_Vprintf("controlField: %d\n", header->controlField);
pp_Vprintf("logMessageInterval: %d\n",
header->logMessageInterval);
pp_Vprintf("\n");
}
}
static void msg_display_announce(MsgAnnounce *announce)
{
if (pp_verbose_dump) {
pp_Vprintf("Message ANNOUNCE:\n");
timestamp_display("Origin Timestamp",
&announce->originTimestamp);
pp_Vprintf("currentUtcOffset: %d\n",
announce->currentUtcOffset);
pp_Vprintf("grandMasterPriority1: %d\n",
announce->grandmasterPriority1);
pp_Vprintf("grandMasterClockQuality:\n");
/* FIXME diag clockQuality_display(&ann->gmasterQuality); */
pp_Vprintf("grandMasterPriority2: %d\n",
announce->grandmasterPriority2);
pp_Vprintf("grandMasterIdentity:\n");
/* FIXME diag clockIdentity_display(ann->gmasterIdentity); */
pp_Vprintf("stepsRemoved: %d\n", announce->stepsRemoved);
pp_Vprintf("timeSource: %d\n", announce->timeSource);
pp_Vprintf("\n");
/* FIXME: diagnostic for extension */
}
}
/* Unpack header from in buffer to msg_tmp_header field */
int msg_unpack_header(struct pp_instance *ppi, void *buf)
int msg_unpack_header(struct pp_instance *ppi, void *buf, int plen)
{
MsgHeader *hdr = &ppi->received_ptp_header;
......@@ -134,8 +53,6 @@ int msg_unpack_header(struct pp_instance *ppi, void *buf)
ppi->is_from_cur_par = 1;
else
ppi->is_from_cur_par = 0;
msg_display_header(hdr);
return 0;
}
......@@ -202,12 +119,6 @@ void msg_unpack_sync(void *buf, MsgSync *sync)
htonl(*(UInteger32 *) (buf + 36));
sync->originTimestamp.nanosecondsField =
htonl(*(UInteger32 *) (buf + 40));
if (pp_verbose_dump) {
PP_VPRINTF("Message SYNC\n");
timestamp_display("Origin Timestamp", &sync->originTimestamp);
PP_VPRINTF("\n");
}
}
/* Pack Announce message into out buffer of ppi */
......@@ -271,7 +182,6 @@ void msg_unpack_announce(void *buf, MsgAnnounce *ann)
if (pp_hooks.unpack_announce)
pp_hooks.unpack_announce(buf, ann);
msg_display_announce(ann);
}
/* Pack Follow Up message into out buffer of ppi*/
......@@ -314,13 +224,6 @@ void msg_unpack_follow_up(void *buf, MsgFollowUp *flwup)
htonl(*(UInteger32 *) (buf + 36));
flwup->preciseOriginTimestamp.nanosecondsField =
htonl(*(UInteger32 *) (buf + 40));
if (pp_verbose_dump) {
PP_VPRINTF("Message FOLLOW_UP\n");
timestamp_display("Precise Origin Timestamp",
&flwup->preciseOriginTimestamp);
PP_VPRINTF("\n");
}
}
/* pack DelayReq message into out buffer of ppi */
......@@ -403,13 +306,6 @@ void msg_unpack_delay_req(void *buf, MsgDelayReq *delay_req)
htonl(*(UInteger32 *) (buf + 36));
delay_req->originTimestamp.nanosecondsField =
htonl(*(UInteger32 *) (buf + 40));
if (pp_verbose_dump) {
PP_VPRINTF("Message DELAY_REQ\n");
timestamp_display("Origin Timestamp",
&delay_req->originTimestamp);
PP_VPRINTF("\n");
}
}
/* Unpack delayResp message from IN buffer of ppi to msgtmp.presp */
......@@ -425,14 +321,6 @@ void msg_unpack_delay_resp(void *buf, MsgDelayResp *resp)
(buf + 44), PP_CLOCK_IDENTITY_LENGTH);
resp->requestingPortIdentity.portNumber =
htons(*(UInteger16 *) (buf + 52));
if (pp_verbose_dump) {
PP_VPRINTF("Message DELAY_RESP\n");
timestamp_display("Receive Timestamp",
&resp->receiveTimestamp);
/* FIXME diag display requestingPortIdentity */
PP_VPRINTF("\n");
}
}
const char const *pp_msg_names[] = {
......
......@@ -9,7 +9,7 @@ STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
CFLAGS = -Wall -ggdb -I../include/ppsi
CFLAGS = -Wall -ggdb -I../include
PROGS = ptpdump adjtime jmptime chktime
LDFLAGS += -lrt
......
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <linux/if_ether.h>
#include <ieee1588_types.h> /* from ../include/ppsi */
#include <ppsi/ieee1588_types.h> /* from ../include */
#include "decent_types.h"
#include "ptpdump.h"
int dumpstruct(FILE *dest, char *prefix, char *name, void *ptr, int size)
static int dumpstruct(char *p1, char *p2, char *name, void *ptr, int size)
{
int ret, i;
unsigned char *p = ptr;
ret = fprintf(dest, "%s%s (size %i)\n", prefix, name, size);
ret = printf("%s%s%s (size %i)\n", p1, p2, name, size);
for (i = 0; i < size; ) {
if ((i & 0xf) == 0)
ret += fprintf(dest, "%s", prefix);
ret += fprintf(dest, "%02x", p[i]);
ret += printf("%s%s", p1, p2);
ret += printf("%02x", p[i]);
i++;
ret += fprintf(dest, i & 3 ? " " : i & 0xf ? " " : "\n");
ret += printf(i & 3 ? " " : i & 0xf ? " " : "\n");
}
if (i & 0xf)
ret += fprintf(dest, "\n");
ret += printf("\n");
return ret;
}
void dump_eth(struct ethhdr *eth)
#if __STDC_HOSTED__
static void dump_time(char *prefix, struct TimeInternal *ti)
{
struct timeval tv;
static struct timeval prev;
struct tm tm;
unsigned char *d = eth->h_dest;
unsigned char *s = eth->h_source;
gettimeofday(&tv, NULL);
if (prev.tv_sec) {
int i;
int diffms;
diffms = (tv.tv_sec - prev.tv_sec) * 1000
+ (signed)(tv.tv_usec + 500 - prev.tv_usec) / 1000;
/* empty lines, one every .25 seconds, at most 10 of them */
for (i = 250; i < 2500 && i < diffms; i += 250)
printf("\n");
printf("TIMEDELTA: %i ms\n", diffms);
}
prev = tv;
tv.tv_sec = ti->seconds;
tv.tv_usec = ti->nanoseconds / 1000;
localtime_r(&tv.tv_sec, &tm);
printf("TIME: (%li - 0x%lx) %02i:%02i:%02i.%06li\n",
printf("%sTIME: (%li - 0x%lx) %02i:%02i:%02i.%06li\n", prefix,
tv.tv_sec, tv.tv_sec,
tm.tm_hour, tm.tm_min, tm.tm_sec, (long)tv.tv_usec);
printf("ETH: %04x (%02x:%02x:%02x:%02x:%02x:%02x -> "
"%02x:%02x:%02x:%02x:%02x:%02x)\n", ntohs(eth->h_proto),
}
#else
static void dump_time(char *prefix, struct TimeInternal *ti)
{
printf("%sTIME: (%li - 0x%lx) %li.%06li\n", prefix, (long)ti->seconds,
(long)ti->seconds, (long)ti->seconds, (long)ti->nanoseconds);
}
#endif
static void dump_eth(char *prefix, struct ethhdr *eth)
{
unsigned char *d = eth->h_dest;
unsigned char *s = eth->h_source;
printf("%sETH: %04x (%02x:%02x:%02x:%02x:%02x:%02x -> "
"%02x:%02x:%02x:%02x:%02x:%02x)\n", prefix, ntohs(eth->h_proto),
s[0], s[1], s[2], s[3], s[4], s[5],
d[0], d[1], d[2], d[3], d[4], d[5]);
}
void dump_ip(struct iphdr *ip)
static void dump_ip(char *prefix, struct iphdr *ip)
{
uint32_t s = ntohl(ip->saddr);
uint32_t d = ntohl(ip->daddr);
printf("IP: %i (%i.%i.%i.%i -> %i.%i.%i.%i) len %i\n",
printf("%sIP: %i (%i.%i.%i.%i -> %i.%i.%i.%i) len %i\n", prefix,
ip->protocol,
(s >> 24) & 0xff, (s >> 16) & 0xff, (s >> 8) & 0xff, s & 0xff,
(d >> 24) & 0xff, (d >> 16) & 0xff, (d >> 8) & 0xff, d & 0xff,
ntohs(ip->tot_len));
}
void dump_udp(struct udphdr *udp)
static void dump_udp(char *prefix, struct udphdr *udp)
{
printf("UDP: (%i -> %i) len %i\n",
printf("%sUDP: (%i -> %i) len %i\n", prefix,
ntohs(udp->source), ntohs(udp->dest), ntohs(udp->len));
}
/* Helpers for fucking data structures */
void dump_1stamp(char *s, struct stamp *t)
static void dump_1stamp(char *prefix, char *s, struct stamp *t)
{
uint64_t sec = (uint64_t)(ntohs(t->sec.msb)) << 32;
sec |= (uint64_t)(ntohl(t->sec.lsb));
printf("%s%lli.%09i\n", s, sec, ntohl(t->nsec));
printf("%s%s%lu.%09i\n", prefix,
s, (unsigned long)sec, ntohl(t->nsec));
}
void dump_1quality(char *s, ClockQuality *q)
static void dump_1quality(char *prefix, char *s, ClockQuality *q)
{
printf("%s%02x-%02x-%04x\n", s, q->clockClass, q->clockAccuracy,
q->offsetScaledLogVariance);
printf("%s%s%02x-%02x-%04x\n", prefix, s, q->clockClass,
q->clockAccuracy, q->offsetScaledLogVariance);
}
void dump_1clockid(char *s, ClockIdentity i)
static void dump_1clockid(char *prefix, char *s, ClockIdentity i)
{
printf("%s%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", s,
printf("%s%s%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", prefix, s,
i.id[0], i.id[1], i.id[2], i.id[3],
i.id[4], i.id[5], i.id[6], i.id[7]);
}
void dump_1port(char *s, unsigned char *p)
static void dump_1port(char *prefix, char *s, unsigned char *p)
{
printf("%s%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", s,
printf("%s%s%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n",
prefix, s,
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
}
/* Helpers for each message types */
void dump_msg_announce(struct ptp_announce *p)
static void dump_msg_announce(char *prefix, struct ptp_announce *p)
{
dump_1stamp("MSG-ANNOUNCE: stamp ", &p->originTimestamp);
dump_1quality("MSG-ANNOUNCE: grandmaster-quality ",
dump_1stamp(prefix, "MSG-ANNOUNCE: stamp ",
&p->originTimestamp);
dump_1quality(prefix, "MSG-ANNOUNCE: grandmaster-quality ",
&p->grandmasterClockQuality);
printf("MSG-ANNOUNCE: grandmaster-prio %i %i\n",
printf("%sMSG-ANNOUNCE: grandmaster-prio %i %i\n", prefix,
p->grandmasterPriority1, p->grandmasterPriority2);
dump_1clockid("MSG-ANNOUNCE: grandmaster-id ",
dump_1clockid(prefix, "MSG-ANNOUNCE: grandmaster-id ",
p->grandmasterIdentity);
}
void dump_msg_sync_etc(char *s, struct ptp_sync_etc *p)
static void dump_msg_sync_etc(char *prefix, char *s, struct ptp_sync_etc *p)
{
dump_1stamp(s, &p->stamp);
dump_1stamp(prefix, s, &p->stamp);
}
void dump_msg_resp_etc(char *s, struct ptp_sync_etc *p)
static void dump_msg_resp_etc(char *prefix, char *s, struct ptp_sync_etc *p)
{
dump_1stamp(s, &p->stamp);
dump_1port(s, p->port);
dump_1stamp(prefix, s, &p->stamp);
dump_1port(prefix, s, p->port);
}
/* TLV dumper, not yet white-rabbit aware */
int dump_tlv(struct ptp_tlv *tlv, int totallen)
static int dump_tlv(char *prefix, struct ptp_tlv *tlv, int totallen)
{
/* the field includes 6 bytes of the header, ecludes 4 of them. Bah! */
int explen = ntohs(tlv->len) + 4;
printf("TLV: type %04x len %i oui %02x:%02x:%02x sub %02x:%02x:%02x\n",
ntohs(tlv->type), explen, tlv->oui[0], tlv->oui[1], tlv->oui[2],
printf("%sTLV: type %04x len %i oui %02x:%02x:%02x "
"sub %02x:%02x:%02x\n", prefix, ntohs(tlv->type), explen,
tlv->oui[0], tlv->oui[1], tlv->oui[2],
tlv->subtype[0], tlv->subtype[1], tlv->subtype[2]);
if (explen > totallen) {
printf("TLV: too short (expected %i, total %i)\n",
printf("%sTLV: too short (expected %i, total %i)\n", prefix,
explen, totallen);
return totallen;
}
......@@ -147,128 +145,135 @@ int dump_tlv(struct ptp_tlv *tlv, int totallen)
/* later: if (memcmp(tlv->oui, "\x08\x00\x30", 3)) ... */
/* Now dump non-wr tlv in binary, count only payload */
dumpstruct(stdout, "TLV: ", "tlv-content", tlv->data,
dumpstruct(prefix, "TLV: ", "tlv-content", tlv->data,
explen - sizeof(*tlv));
return explen;
}
/* A big function to dump the ptp information */
void dump_payload(void *pl, int len)
static void dump_payload(char *prefix, void *pl, int len)
{
struct ptp_header *h = pl;
void *msg_specific = (void *)(h + 1);
int donelen = 34; /* packet length before tlv */
if (h->versionPTP != 2) {
printf("VERSION: unsupported (%i)\n", h->versionPTP);
printf("%sVERSION: unsupported (%i)\n", prefix, h->versionPTP);
return;
}
printf("VERSION: %i (type %i, len %i, domain %i)\n",
printf("%sVERSION: %i (type %i, len %i, domain %i)\n", prefix,
h->versionPTP, h->messageType,
ntohs(h->messageLength), h->domainNumber);
printf("FLAGS: 0x%04x (correction 0x%08llx)\n", h->flagField,
h->correctionField);
dump_1port("PORT: ", h->sourcePortIdentity);
printf("REST: seq %i, ctrl %i, log-interval %i\n",
printf("%sFLAGS: 0x%04x (correction 0x%08lu)\n", prefix, h->flagField,
(unsigned long)h->correctionField);
dump_1port(prefix, "PORT: ", h->sourcePortIdentity);
printf("%sREST: seq %i, ctrl %i, log-interval %i\n", prefix,
ntohs(h->sequenceId), h->controlField, h->logMessageInterval);
#define CASE(t, x) case PPM_ ##x: printf("MESSAGE: (" #t ") " #x "\n")
#define CASE(t, x) case PPM_ ##x: printf("%sMESSAGE: (" #t ") " #x "\n", prefix)
switch(h->messageType) {
CASE(E, SYNC);
dump_msg_sync_etc("MSG-SYNC: ", msg_specific);
dump_msg_sync_etc(prefix, "MSG-SYNC: ", msg_specific);
donelen = 44;
break;
CASE(E, DELAY_REQ);
dump_msg_sync_etc("MSG-DELAY_REQ: ", msg_specific);
dump_msg_sync_etc(prefix, "MSG-DELAY_REQ: ", msg_specific);
donelen = 44;
break;
CASE(E, PDELAY_REQ);
dump_msg_sync_etc("MSG-PDELAY_REQ: ", msg_specific);
donelen = 54;
break;
CASE(E, PDELAY_RESP);
dump_msg_resp_etc("MSG-PDELAY_RESP: ", msg_specific);
donelen = 54;
break;
CASE(G, FOLLOW_UP);
dump_msg_sync_etc("MSG-FOLLOW_UP: ", msg_specific);
dump_msg_sync_etc(prefix, "MSG-FOLLOW_UP: ", msg_specific);
donelen = 44;
break;
CASE(G, DELAY_RESP);
dump_msg_resp_etc("MSG-DELAY_RESP: ", msg_specific);
donelen = 54;
break;
CASE(G, PDELAY_RESP_FOLLOW_UP);
dump_msg_resp_etc("MSG-PDELAY_RESP_FOLLOWUP: ", msg_specific);
dump_msg_resp_etc(prefix, "MSG-DELAY_RESP: ", msg_specific);
donelen = 54;
break;
CASE(G, ANNOUNCE);
dump_msg_announce(msg_specific);
dump_msg_announce(prefix, msg_specific);
donelen = 64;
break;
CASE(G, SIGNALING);
dump_1port("MSG-SIGNALING: target-port ", msg_specific);
dump_1port(prefix, "MSG-SIGNALING: target-port ", msg_specific);
donelen = 44;
break;
#if __STDC_HOSTED__ /* Avoid pdelay dump withing ppsi, we don't use it */
CASE(E, PDELAY_REQ);
dump_msg_sync_etc(prefix, "MSG-PDELAY_REQ: ", msg_specific);
donelen = 54;
break;
CASE(E, PDELAY_RESP);
dump_msg_resp_etc(prefix, "MSG-PDELAY_RESP: ", msg_specific);
donelen = 54;
break;
CASE(G, PDELAY_RESP_FOLLOW_UP);
dump_msg_resp_etc(prefix, "MSG-PDELAY_RESP_FOLLOWUP: ",
msg_specific);
donelen = 54;
break;
CASE(G, MANAGEMENT);
/* FIXME */
break;
#endif
}
/* Dump any trailing TLV */
while (donelen < len) {
int n = len - donelen;
if (n < sizeof(struct ptp_tlv)) {
printf("TLV: too short (%i - %i = %i)\n", len,
donelen, n);
printf("%sTLV: too short (%i - %i = %i)\n", prefix,
len, donelen, n);
break;
}
donelen += dump_tlv(pl + donelen, n);
donelen += dump_tlv(prefix, pl + donelen, n);
}
/* Finally, binary dump of it all */
dumpstruct(stdout, "DUMP: ", "payload", pl, len);
dumpstruct(prefix, "DUMP: ", "payload", pl, len);
}
int dump_udppkt(void *buf, int len)
/* This dumps a complete udp frame, starting from the eth header */
int dump_udppkt(char *prefix, void *buf, int len, struct TimeInternal *ti)
{
struct ethhdr *eth = buf;
struct iphdr *ip = buf + ETH_HLEN;
struct udphdr *udp = (void *)(ip + 1);
void *payload = (void *)(udp + 1);
int udpdest = ntohs(udp->dest);
if (len < ETH_HLEN + sizeof(*ip) + sizeof(*udp))
return -1;
/* page 239 and following */
if (udpdest != 319 && udpdest != 320)
return -1;
if (ti)
dump_time(prefix, ti);
dump_eth(prefix, eth);
dump_ip(prefix, ip);
dump_udp(prefix, udp);
dump_payload(prefix, payload, len - (payload - buf));
return 0;
}
dump_eth(eth);
dump_ip(ip);
dump_udp(udp);
dump_payload(payload, len - (payload - buf));
putchar('\n');
/* This dumps the payload only, used for udp frames without headers */
int dump_payloadpkt(char *prefix, void *buf, int len, struct TimeInternal *ti)
{
if (ti)
dump_time(prefix, ti);
dump_payload(prefix, buf, len);
return 0;
}
int dump_1588pkt(void *buf, int len)
/* This dumps everything, used for raw frames with headers and ptp payload */
int dump_1588pkt(char *prefix, void *buf, int len, struct TimeInternal *ti)
{
struct ethhdr *eth = buf;
void *payload = (void *)(eth + 1);
dump_eth(eth);
dump_payload(payload, len - (payload - buf));
putchar('\n');
if (ti)
dump_time(prefix, ti);
dump_eth(prefix, eth);
dump_payload(prefix, payload, len - (payload - buf));
return 0;
}
......@@ -18,7 +18,7 @@
#include <net/if_arp.h>
#include <netpacket/packet.h>
#include <ieee1588_types.h> /* from ../include/ppsi */
#include <ppsi/ieee1588_types.h> /* from ../include */
#include "decent_types.h"
#include "ptpdump.h"
......@@ -26,9 +26,28 @@
#define ETH_P_1588 0x88F7
#endif
void print_spaces(struct TimeInternal *ti)
{
static struct TimeInternal prev_ti;
int i, diffms;
if (prev_ti.seconds) {
diffms = (ti->seconds - prev_ti.seconds) * 1000
+ (ti->nanoseconds / 1000 / 1000)
- (prev_ti.nanoseconds / 1000 / 1000);
/* empty lines, one every .25 seconds, at most 10 of them */
for (i = 250; i < 2500 && i < diffms; i += 250)
printf("\n");
printf("TIMEDELTA: %i ms\n", diffms);
}
prev_ti = *ti;
}
int main(int argc, char **argv)
{
int sock;
int sock, ret;
struct packet_mreq req;
struct ifreq ifr;
char *ifname = "eth0";
......@@ -68,6 +87,8 @@ int main(int argc, char **argv)
static unsigned char prev[1500];
static int prevlen;
unsigned char buf[1500];
struct TimeInternal ti;
struct timeval tv;
struct sockaddr_in from;
socklen_t fromlen = sizeof(from);
......@@ -75,6 +96,12 @@ int main(int argc, char **argv)
len = recvfrom(sock, buf, sizeof(buf), MSG_TRUNC,
(struct sockaddr *) &from, &fromlen);
/* Get the receive time, copy it to TimeInternal */
gettimeofday(&tv, NULL);
ti.seconds = tv.tv_sec;
ti.nanoseconds = tv.tv_usec * 1000;
if (len > sizeof(buf))
len = sizeof(buf);
/* for some reasons, we receive it three times, check dups */
......@@ -89,18 +116,35 @@ int main(int argc, char **argv)
ip = (void *)(buf + ETH_HLEN);
switch(ntohs(eth->h_proto)) {
case ETH_P_IP:
if (len < ETH_HLEN + sizeof(*ip))
{
struct udphdr *udp = (void *)(ip + 1);
int udpdest = ntohs(udp->dest);
/*
* Filter before calling the dump function, otherwise
* we'll report TIMEDELAY for not-relevant frames
*/
if (len < ETH_HLEN + sizeof(*ip) + sizeof(*udp))
continue;
if (ip->protocol != IPPROTO_UDP)
continue;
dump_udppkt(buf, len);
if (udpdest != 319 && udpdest != 320)
continue;
print_spaces(&ti);
ret = dump_udppkt("", buf, len, &ti);
break;
}
case ETH_P_1588:
dump_1588pkt(buf, len);
print_spaces(&ti);
ret = dump_1588pkt("", buf, len, &ti);
break;
default:
ret = -1;
continue;
}
if (ret == 0)
putchar('\n');
fflush(stdout);
}
......
#ifndef __PTPDUMP_H__
#define __PTPDUMP_H__
int dumpstruct(FILE *dest, char *prefix, char *name, void *ptr, int size);
void dump_eth(struct ethhdr *eth);
void dump_ip(struct iphdr *ip);
void dump_udp(struct udphdr *udp);
void dump_1stamp(char *s, struct stamp *t);
void dump_1quality(char *s, ClockQuality *q);
void dump_1clockid(char *s, ClockIdentity i);
void dump_1port(char *s, unsigned char *p);
void dump_msg_announce(struct ptp_announce *p);
void dump_msg_sync_etc(char *s, struct ptp_sync_etc *p);
void dump_msg_resp_etc(char *s, struct ptp_sync_etc *p);
int dump_tlv(struct ptp_tlv *tlv, int totallen);
void dump_payload(void *pl, int len);
int dump_udppkt(void *buf, int len);
int dump_1588pkt(void *buf, int len);
#if __STDC_HOSTED__
#include <time.h>
#include <sys/time.h>
#include <netinet/ip.h> /* struct iphdr */
#include <netinet/udp.h> /* struct udphdr */
#include <linux/if_ether.h> /* struct ethhdr */
#else
#include <ppsi/ppsi.h>
#include "../lib/network_types.h"
#define printf pp_printf
#endif
int dump_udppkt(char *prefix, void *buf, int len, struct TimeInternal *ti);
int dump_payloadpkt(char *prefix, void *buf, int len, struct TimeInternal *ti);
int dump_1588pkt(char *prefix, void *buf, int len, struct TimeInternal *ti);
#endif /* __PTPDUMP_H__ */
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