state-master.c 3.12 KB
Newer Older
1
/*
2 3
 * Copyright (C) 2011 CERN (www.cern.ch)
 * Author: Aurelio Colosimo
4
 * Based on PTPd project v. 2.1.0 (see AUTHORS for details)
5 6
 *
 * Released according to the GNU LGPL, version 2.1 or any later version.
7
 */
8

Alessandro Rubini's avatar
Alessandro Rubini committed
9
#include <ppsi/ppsi.h>
10
#include "common-fun.h"
11

12 13 14 15 16 17 18 19 20 21 22 23 24
static int master_handle_delay_request(struct pp_instance *ppi,
				       unsigned char *pkt, int plen);

static pp_action *actions[] = {
	[PPM_SYNC]		= st_com_master_handle_sync,
	[PPM_DELAY_REQ]		= master_handle_delay_request,
#if CONFIG_HAS_P2P
	[PPM_PDELAY_REQ]	= st_com_peer_handle_preq,
	[PPM_PDELAY_RESP]	= st_com_peer_handle_pres,
	[PPM_PDELAY_R_FUP]	= st_com_peer_handle_pres_followup,
#endif
	[PPM_FOLLOW_UP]		= 0,
	[PPM_DELAY_RESP]	= 0,
25
	[PPM_ANNOUNCE]		= pp_lib_handle_announce,
26 27 28 29 30 31 32 33 34 35 36
	/* skip signaling and management, for binary size */
};

static int master_handle_delay_request(struct pp_instance *ppi,
				       unsigned char *pkt, int plen)
{
	if (ppi->state == PPS_MASTER) /* not pre-master */
		msg_issue_delay_resp(ppi, &ppi->last_rcv_time);
	return 0;
}

37
/*
38
 * MASTER and PRE_MASTER have many things in common. This function implements
39
 * both states. We set "pre" internally to 0 or 1.
40
 */
41
int pp_master(struct pp_instance *ppi, uint8_t *pkt, int plen)
42
{
43
	int msgtype;
44
	int pre = (ppi->state == PPS_PRE_MASTER);
45
	int e = 0; /* error var, to check errors in msg handling */
46

47
	/* upgrade from pre-master to master */
48 49 50 51 52 53 54 55 56 57 58 59 60
	if (pre && pp_timeout(ppi, PP_TO_QUALIFICATION)) {
		ppi->next_state = PPS_MASTER;
		return 0;
	}

	if (!pre) {
		/*
		 * ignore errors; we are not getting FAULTY if not
		 * transmitting
		 */
		pp_lib_may_issue_sync(ppi);
		pp_lib_may_issue_announce(ppi);
	}
61

62
	/* when the clock is using peer-delay, the master must send it too */
63
	if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
64
		pp_lib_may_issue_request(ppi);
65 66
	else /* please check commit '6d7bf7e3' about below, I'm not sure */
		pp_timeout_set(ppi, PP_TO_REQUEST);
67

68 69 70
	/*
	 * An extension can do special treatment of this message type,
	 * possibly returning error or eating the message by returning
71
	 * PPM_NO_MESSAGE
72
	 */
73
	msgtype = ppi->received_ptp_header.messageType;
74 75 76 77
	if (pp_hooks.master_msg)
		msgtype = pp_hooks.master_msg(ppi, pkt, plen, msgtype);
	if (msgtype < 0) {
		e = msgtype;
78 79 80
		plen = 0;
		e = PP_SEND_ERROR; /* well, "error" in general */
		goto out;
81 82
	}

83 84 85
	/*
	 * The management of messages is now table-driven
	 */
86
	if (msgtype < ARRAY_SIZE(actions)
87 88 89
	    && actions[msgtype]) {
		e = actions[msgtype](ppi, pkt, plen);
	} else {
90 91 92
		if (plen && msgtype != PPM_NO_MESSAGE)
			pp_diag(ppi, frames, 1, "Ignored frame %i\n",
				msgtype);
93 94
	}

95
out:
96 97
	switch(e) {
	case PP_SEND_OK: /* 0 */
98
		/* Why should we switch to slave? Remove this code? */
99
		if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY
100
		    || (ppi->role == PPSI_ROLE_SLAVE))
101
			ppi->next_state = PPS_LISTENING;
102 103
		break;
	case PP_SEND_ERROR:
104
		/* fall through: a lost frame is not the end of the world */
105 106 107 108
	case PP_SEND_NO_STAMP:
		/* nothing, just keep the ball rolling */
		e = 0;
		break;
109
	}
110

111
	/* we also use TO_QUALIFICATION, but avoid counting it here */
112 113
	ppi->next_delay = pp_next_delay_3(ppi,
		PP_TO_ANN_SEND, PP_TO_SYNC_SEND, PP_TO_REQUEST);
114
	return e;
115
}
116