Blame unicast_client.c

Packit 9c3e7e
/**
Packit 9c3e7e
 * @file unicast_client.c
Packit 9c3e7e
 * @brief Unicast client implementation
Packit 9c3e7e
 * @note Copyright (C) 2018 Richard Cochran <richardcochran@gmail.com>
Packit 9c3e7e
 *
Packit 9c3e7e
 * This program is free software; you can redistribute it and/or modify
Packit 9c3e7e
 * it under the terms of the GNU General Public License as published by
Packit 9c3e7e
 * the Free Software Foundation; either version 2 of the License, or
Packit 9c3e7e
 * (at your option) any later version.
Packit 9c3e7e
 *
Packit 9c3e7e
 * This program is distributed in the hope that it will be useful,
Packit 9c3e7e
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 9c3e7e
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 9c3e7e
 * GNU General Public License for more details.
Packit 9c3e7e
 *
Packit 9c3e7e
 * You should have received a copy of the GNU General Public License along
Packit 9c3e7e
 * with this program; if not, write to the Free Software Foundation, Inc.,
Packit 9c3e7e
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA.
Packit 9c3e7e
 */
Packit 9c3e7e
#include "port.h"
Packit 9c3e7e
#include "port_private.h"
Packit 9c3e7e
#include "print.h"
Packit 9c3e7e
#include "unicast_client.h"
Packit 9c3e7e
Packit 9c3e7e
#define E2E_SYDY_MASK	(1 << ANNOUNCE | 1 << SYNC | 1 << DELAY_RESP)
Packit 9c3e7e
#define P2P_SYDY_MASK	(1 << ANNOUNCE | 1 << SYNC)
Packit 9c3e7e
Packit 9c3e7e
static struct PortIdentity wildcard = {
Packit 9c3e7e
	.clockIdentity = {
Packit 9c3e7e
		{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
Packit 9c3e7e
	},
Packit 9c3e7e
	.portNumber = 0xffff,
Packit 9c3e7e
};
Packit 9c3e7e
Packit 9c3e7e
static int attach_ack(struct ptp_message *msg, uint8_t message_type_flags)
Packit 9c3e7e
{
Packit 9c3e7e
	struct ack_cancel_unicast_xmit_tlv *ack;
Packit 9c3e7e
	struct tlv_extra *extra;
Packit 9c3e7e
Packit 9c3e7e
	extra = msg_tlv_append(msg, sizeof(*ack));
Packit 9c3e7e
	if (!extra) {
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
	ack = (struct ack_cancel_unicast_xmit_tlv *) extra->tlv;
Packit 9c3e7e
	ack->type = TLV_ACKNOWLEDGE_CANCEL_UNICAST_TRANSMISSION;
Packit 9c3e7e
	ack->length = sizeof(*ack) - sizeof(ack->type) - sizeof(ack->length);
Packit 9c3e7e
	ack->message_type_flags = message_type_flags;
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int attach_request(struct ptp_message *msg, int log_period,
Packit 9c3e7e
			  uint8_t message_type, int duration)
Packit 9c3e7e
{
Packit 9c3e7e
	struct request_unicast_xmit_tlv *req;
Packit 9c3e7e
	struct tlv_extra *extra;
Packit 9c3e7e
Packit 9c3e7e
	extra = msg_tlv_append(msg, sizeof(*req));
Packit 9c3e7e
	if (!extra) {
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
	req = (struct request_unicast_xmit_tlv *) extra->tlv;
Packit 9c3e7e
	req->type = TLV_REQUEST_UNICAST_TRANSMISSION;
Packit 9c3e7e
	req->length = sizeof(*req) - sizeof(req->type) - sizeof(req->length);
Packit 9c3e7e
	req->message_type = message_type << 4;
Packit 9c3e7e
	req->logInterMessagePeriod = log_period;
Packit 9c3e7e
	req->durationField = duration;
Packit 9c3e7e
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int unicast_client_announce(struct port *p,
Packit 9c3e7e
				   struct unicast_master_address *dst)
Packit 9c3e7e
{
Packit 9c3e7e
	struct ptp_message *msg;
Packit 9c3e7e
	int err;
Packit 9c3e7e
Packit 9c3e7e
	msg = port_signaling_construct(p, &dst->address, &dst->portIdentity);
Packit 9c3e7e
	if (!msg) {
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
	err = attach_request(msg, p->logAnnounceInterval, ANNOUNCE,
Packit 9c3e7e
			     p->unicast_req_duration);
Packit 9c3e7e
	if (err) {
Packit 9c3e7e
		goto out;
Packit 9c3e7e
	}
Packit 9c3e7e
	err = port_prepare_and_send(p, msg, TRANS_GENERAL);
Packit 9c3e7e
	if (err) {
Packit 9c3e7e
		pr_err("port %hu: signaling message failed", portnum(p));
Packit 9c3e7e
	}
Packit 9c3e7e
out:
Packit 9c3e7e
	msg_put(msg);
Packit 9c3e7e
	return err;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static struct unicast_master_address *unicast_client_ok(struct port *p,
Packit 9c3e7e
							struct ptp_message *m)
Packit 9c3e7e
{
Packit 9c3e7e
	struct unicast_master_address *ucma;
Packit 9c3e7e
Packit 9c3e7e
	if (!unicast_client_enabled(p)) {
Packit 9c3e7e
		return NULL;
Packit 9c3e7e
	}
Packit 9c3e7e
	if (!pid_eq(&m->signaling.targetPortIdentity, &p->portIdentity) &&
Packit 9c3e7e
	    !pid_eq(&m->signaling.targetPortIdentity, &wildcard)) {
Packit 9c3e7e
		return NULL;
Packit 9c3e7e
	}
Packit 9c3e7e
	STAILQ_FOREACH(ucma, &p->unicast_master_table->addrs, list) {
Packit 9c3e7e
		if (addreq(transport_type(p->trp), &ucma->address, &m->address)) {
Packit 9c3e7e
			break;
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
	if (!ucma) {
Packit 9c3e7e
		pr_warning("port %d: received rogue unicast grant or cancel",
Packit 9c3e7e
			   portnum(p));
Packit 9c3e7e
		return NULL;
Packit 9c3e7e
	}
Packit 9c3e7e
	return ucma;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int unicast_client_peer_renew(struct port *p)
Packit 9c3e7e
{
Packit 9c3e7e
	struct unicast_master_address *peer;
Packit 9c3e7e
	struct ptp_message *msg;
Packit 9c3e7e
	struct timespec now;
Packit 9c3e7e
	int err;
Packit 9c3e7e
Packit 9c3e7e
	if (!p->unicast_master_table->peer_name) {
Packit 9c3e7e
		return 0;
Packit 9c3e7e
	}
Packit 9c3e7e
	err = clock_gettime(CLOCK_MONOTONIC, &now;;
Packit 9c3e7e
	if (err) {
Packit 9c3e7e
		pr_err("clock_gettime failed: %m");
Packit 9c3e7e
		return err;
Packit 9c3e7e
	}
Packit 9c3e7e
	peer = &p->unicast_master_table->peer_addr;
Packit 9c3e7e
	if (now.tv_sec < peer->renewal_tmo) {
Packit 9c3e7e
		return 0;
Packit 9c3e7e
	}
Packit 9c3e7e
	peer->renewal_tmo = 0;
Packit 9c3e7e
	pr_debug("port %d: time to renew P2P unicast subscription", portnum(p));
Packit 9c3e7e
Packit 9c3e7e
	msg = port_signaling_construct(p, &peer->address, &peer->portIdentity);
Packit 9c3e7e
	if (!msg) {
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
	err = attach_request(msg, p->logMinPdelayReqInterval, PDELAY_RESP,
Packit 9c3e7e
			     p->unicast_req_duration);
Packit 9c3e7e
	if (err) {
Packit 9c3e7e
		goto out;
Packit 9c3e7e
	}
Packit 9c3e7e
	err = port_prepare_and_send(p, msg, TRANS_GENERAL);
Packit 9c3e7e
	if (err) {
Packit 9c3e7e
		pr_err("port %hu: P2P signaling message failed", portnum(p));
Packit 9c3e7e
	}
Packit 9c3e7e
out:
Packit 9c3e7e
	msg_put(msg);
Packit 9c3e7e
	return err;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int unicast_client_renew(struct port *p,
Packit 9c3e7e
				struct unicast_master_address *dst)
Packit 9c3e7e
{
Packit 9c3e7e
	struct ptp_message *msg;
Packit 9c3e7e
	struct timespec now;
Packit 9c3e7e
	int err;
Packit 9c3e7e
Packit 9c3e7e
	err = clock_gettime(CLOCK_MONOTONIC, &now;;
Packit 9c3e7e
	if (err) {
Packit 9c3e7e
		pr_err("clock_gettime failed: %m");
Packit 9c3e7e
		return err;
Packit 9c3e7e
	}
Packit 9c3e7e
	if (now.tv_sec < dst->renewal_tmo) {
Packit 9c3e7e
		return 0;
Packit 9c3e7e
	}
Packit 9c3e7e
	dst->renewal_tmo = 0;
Packit 9c3e7e
	pr_debug("port %d: time to renew unicast subscriptions", portnum(p));
Packit 9c3e7e
Packit 9c3e7e
	msg = port_signaling_construct(p, &dst->address, &dst->portIdentity);
Packit 9c3e7e
	if (!msg) {
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
	err = attach_request(msg, p->logAnnounceInterval, ANNOUNCE,
Packit 9c3e7e
			     p->unicast_req_duration);
Packit 9c3e7e
	if (err) {
Packit 9c3e7e
		goto out;
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	if (dst->state == UC_HAVE_SYDY) {
Packit 9c3e7e
		err = attach_request(msg, p->logSyncInterval, SYNC,
Packit 9c3e7e
				     p->unicast_req_duration);
Packit 9c3e7e
		if (err) {
Packit 9c3e7e
			goto out;
Packit 9c3e7e
		}
Packit 9c3e7e
		if (p->delayMechanism != DM_P2P) {
Packit 9c3e7e
			err = attach_request(msg, p->logMinDelayReqInterval,
Packit 9c3e7e
					     DELAY_RESP,
Packit 9c3e7e
					     p->unicast_req_duration);
Packit 9c3e7e
			if (err) {
Packit 9c3e7e
				goto out;
Packit 9c3e7e
			}
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	err = port_prepare_and_send(p, msg, TRANS_GENERAL);
Packit 9c3e7e
	if (err) {
Packit 9c3e7e
		pr_err("port %hu: signaling message failed", portnum(p));
Packit 9c3e7e
	}
Packit 9c3e7e
out:
Packit 9c3e7e
	msg_put(msg);
Packit 9c3e7e
	return err;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static void unicast_client_set_renewal(struct port *p,
Packit 9c3e7e
				       struct unicast_master_address *master,
Packit 9c3e7e
				       long duration)
Packit 9c3e7e
{
Packit 9c3e7e
	struct timespec now;
Packit 9c3e7e
	long tmo;
Packit 9c3e7e
Packit 9c3e7e
	if (clock_gettime(CLOCK_MONOTONIC, &now)) {
Packit 9c3e7e
		pr_err("clock_gettime failed: %m");
Packit 9c3e7e
		return;
Packit 9c3e7e
	}
Packit 9c3e7e
	duration = (3 * duration) / 4;
Packit 9c3e7e
	tmo = now.tv_sec + duration;
Packit 9c3e7e
	if (!master->renewal_tmo || tmo < master->renewal_tmo) {
Packit 9c3e7e
		master->renewal_tmo = tmo;
Packit 9c3e7e
		pr_debug("port %d: renewal timeout at %ld", portnum(p), tmo);
Packit 9c3e7e
	}
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
static int unicast_client_sydy(struct port *p,
Packit 9c3e7e
			       struct unicast_master_address *dst)
Packit 9c3e7e
{
Packit 9c3e7e
	struct ptp_message *msg;
Packit 9c3e7e
	int err;
Packit 9c3e7e
Packit 9c3e7e
	msg = port_signaling_construct(p, &dst->address, &dst->portIdentity);
Packit 9c3e7e
	if (!msg) {
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
	err = attach_request(msg, p->logSyncInterval, SYNC,
Packit 9c3e7e
			     p->unicast_req_duration);
Packit 9c3e7e
	if (err) {
Packit 9c3e7e
		goto out;
Packit 9c3e7e
	}
Packit 9c3e7e
	if (p->delayMechanism != DM_P2P) {
Packit 9c3e7e
		err = attach_request(msg, p->logMinDelayReqInterval, DELAY_RESP,
Packit 9c3e7e
				     p->unicast_req_duration);
Packit 9c3e7e
		if (err) {
Packit 9c3e7e
			goto out;
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
	err = port_prepare_and_send(p, msg, TRANS_GENERAL);
Packit 9c3e7e
	if (err) {
Packit 9c3e7e
		pr_err("port %hu: signaling message failed", portnum(p));
Packit 9c3e7e
	}
Packit 9c3e7e
out:
Packit 9c3e7e
	msg_put(msg);
Packit 9c3e7e
	return err;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
/* public methods */
Packit 9c3e7e
Packit 9c3e7e
int unicast_client_cancel(struct port *p, struct ptp_message *m,
Packit 9c3e7e
			  struct tlv_extra *extra)
Packit 9c3e7e
{
Packit 9c3e7e
	struct cancel_unicast_xmit_tlv *cancel;
Packit 9c3e7e
	struct unicast_master_address *ucma;
Packit 9c3e7e
	struct ptp_message *msg;
Packit 9c3e7e
	uint8_t mtype;
Packit 9c3e7e
	int err;
Packit 9c3e7e
Packit 9c3e7e
	ucma = unicast_client_ok(p, m);
Packit 9c3e7e
	if (!ucma) {
Packit 9c3e7e
		return 0;
Packit 9c3e7e
	}
Packit 9c3e7e
	cancel = (struct cancel_unicast_xmit_tlv *) extra->tlv;
Packit 9c3e7e
	mtype = cancel->message_type_flags >> 4;
Packit 9c3e7e
	switch (mtype) {
Packit 9c3e7e
	case ANNOUNCE:
Packit 9c3e7e
	case SYNC:
Packit 9c3e7e
	case DELAY_RESP:
Packit 9c3e7e
		break;
Packit 9c3e7e
	default:
Packit 9c3e7e
		return 0;
Packit 9c3e7e
	}
Packit 9c3e7e
	if (cancel->message_type_flags & CANCEL_UNICAST_MAINTAIN_GRANT) {
Packit 9c3e7e
		return 0;
Packit 9c3e7e
	}
Packit 9c3e7e
	pr_warning("port %d: server unilaterally canceled unicast %s grant",
Packit 9c3e7e
		   portnum(p), msg_type_string(mtype));
Packit 9c3e7e
Packit 9c3e7e
	ucma->state = unicast_fsm(ucma->state, UC_EV_CANCEL);
Packit 9c3e7e
	ucma->granted &= ~(1 << mtype);
Packit 9c3e7e
Packit 9c3e7e
	/* Respond with ACK. */
Packit 9c3e7e
	msg = port_signaling_construct(p, &ucma->address, &ucma->portIdentity);
Packit 9c3e7e
	if (!msg) {
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
	err = attach_ack(msg, cancel->message_type_flags);
Packit 9c3e7e
	if (err) {
Packit 9c3e7e
		goto out;
Packit 9c3e7e
	}
Packit 9c3e7e
	err = port_prepare_and_send(p, msg, TRANS_GENERAL);
Packit 9c3e7e
	if (err) {
Packit 9c3e7e
		pr_err("port %hu: signaling message failed", portnum(p));
Packit 9c3e7e
	}
Packit 9c3e7e
out:
Packit 9c3e7e
	msg_put(msg);
Packit 9c3e7e
	return err;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int unicast_client_claim_table(struct port *p)
Packit 9c3e7e
{
Packit 9c3e7e
	struct unicast_master_address *master, *peer;
Packit 9c3e7e
	struct config *cfg = clock_config(p->clock);
Packit 9c3e7e
	struct unicast_master_table *table;
Packit 9c3e7e
	int table_id;
Packit 9c3e7e
Packit 9c3e7e
	table_id = config_get_int(cfg, p->name, "unicast_master_table");
Packit 9c3e7e
	if (!table_id) {
Packit 9c3e7e
		return 0;
Packit 9c3e7e
	}
Packit 9c3e7e
	STAILQ_FOREACH(table, &cfg->unicast_master_tables, list) {
Packit 9c3e7e
		if (table->table_index == table_id) {
Packit 9c3e7e
			break;
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
	if (!table) {
Packit 9c3e7e
		pr_err("port %d: no table with id %d", portnum(p), table_id);
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
	if (table->port) {
Packit 9c3e7e
		pr_err("port %d: table %d already claimed by port %d",
Packit 9c3e7e
		       portnum(p), table_id, table->port);
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
	peer = &table->peer_addr;
Packit 9c3e7e
	if (table->peer_name && str2addr(transport_type(p->trp),
Packit 9c3e7e
					 table->peer_name, &peer->address)) {
Packit 9c3e7e
		pr_err("port %d: bad peer address: %s",
Packit 9c3e7e
		       portnum(p), table->peer_name);
Packit 9c3e7e
		return -1;
Packit 9c3e7e
	}
Packit 9c3e7e
	STAILQ_FOREACH(master, &table->addrs, list) {
Packit 9c3e7e
		if (master->type != transport_type(p->trp)) {
Packit 9c3e7e
			pr_warning("port %d: unicast master transport mismatch",
Packit 9c3e7e
				   portnum(p));
Packit 9c3e7e
		}
Packit 9c3e7e
		if (p->delayMechanism == DM_P2P) {
Packit 9c3e7e
			master->sydymsk = P2P_SYDY_MASK;
Packit 9c3e7e
		} else {
Packit 9c3e7e
			master->sydymsk = E2E_SYDY_MASK;
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
	table->port = portnum(p);
Packit 9c3e7e
	p->unicast_master_table = table;
Packit 9c3e7e
	p->unicast_req_duration =
Packit 9c3e7e
		config_get_int(cfg, p->name, "unicast_req_duration");
Packit 9c3e7e
	return 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int unicast_client_enabled(struct port *p)
Packit 9c3e7e
{
Packit 9c3e7e
	return p->unicast_master_table ? 1 : 0;
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
void unicast_client_grant(struct port *p, struct ptp_message *m,
Packit 9c3e7e
			  struct tlv_extra *extra)
Packit 9c3e7e
{
Packit 9c3e7e
	struct unicast_master_address *ucma;
Packit 9c3e7e
	struct grant_unicast_xmit_tlv *g;
Packit 9c3e7e
	int mtype;
Packit 9c3e7e
Packit 9c3e7e
	ucma = unicast_client_ok(p, m);
Packit 9c3e7e
	if (!ucma) {
Packit 9c3e7e
		return;
Packit 9c3e7e
	}
Packit 9c3e7e
	g = (struct grant_unicast_xmit_tlv *) extra->tlv;
Packit 9c3e7e
	mtype = g->message_type >> 4;
Packit 9c3e7e
Packit 9c3e7e
	if (!g->durationField) {
Packit 9c3e7e
		pr_warning("port %d: unicast grant of %s rejected",
Packit 9c3e7e
			   portnum(p), msg_type_string(mtype));
Packit 9c3e7e
		if (mtype != PDELAY_RESP) {
Packit 9c3e7e
			ucma->state = UC_WAIT;
Packit 9c3e7e
		}
Packit 9c3e7e
		return;
Packit 9c3e7e
	}
Packit 9c3e7e
	pr_debug("port %d: unicast %s granted for %u sec",
Packit 9c3e7e
		 portnum(p), msg_type_string(mtype), g->durationField);
Packit 9c3e7e
Packit 9c3e7e
	if (p->delayMechanism == DM_P2P) {
Packit 9c3e7e
		switch (mtype) {
Packit 9c3e7e
		case DELAY_RESP:
Packit 9c3e7e
			return;
Packit 9c3e7e
		case PDELAY_RESP:
Packit 9c3e7e
			p->unicast_master_table->peer_addr.portIdentity =
Packit 9c3e7e
				m->header.sourcePortIdentity;
Packit 9c3e7e
			unicast_client_set_renewal(p,
Packit 9c3e7e
				&p->unicast_master_table->peer_addr,
Packit 9c3e7e
				g->durationField);
Packit 9c3e7e
			p->logMinPdelayReqInterval = g->logInterMessagePeriod;
Packit 9c3e7e
			return;
Packit 9c3e7e
		default:
Packit 9c3e7e
			break;
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	ucma->granted |= 1 << mtype;
Packit 9c3e7e
Packit 9c3e7e
	switch (ucma->state) {
Packit 9c3e7e
	case UC_WAIT:
Packit 9c3e7e
		if (mtype == ANNOUNCE) {
Packit 9c3e7e
			ucma->state = unicast_fsm(ucma->state, UC_EV_GRANT_ANN);
Packit 9c3e7e
			ucma->portIdentity = m->header.sourcePortIdentity;
Packit 9c3e7e
			unicast_client_set_renewal(p, ucma, g->durationField);
Packit 9c3e7e
		}
Packit 9c3e7e
		break;
Packit 9c3e7e
	case UC_HAVE_ANN:
Packit 9c3e7e
		break;
Packit 9c3e7e
	case UC_NEED_SYDY:
Packit 9c3e7e
		switch (mtype) {
Packit 9c3e7e
		case DELAY_RESP:
Packit 9c3e7e
			if ((ucma->granted & ucma->sydymsk) == ucma->sydymsk) {
Packit 9c3e7e
				ucma->state = unicast_fsm(ucma->state,
Packit 9c3e7e
							  UC_EV_GRANT_SYDY);
Packit 9c3e7e
			}
Packit 9c3e7e
			unicast_client_set_renewal(p, ucma, g->durationField);
Packit 9c3e7e
			p->logMinDelayReqInterval = g->logInterMessagePeriod;
Packit 9c3e7e
			break;
Packit 9c3e7e
		case SYNC:
Packit 9c3e7e
			if ((ucma->granted & ucma->sydymsk) == ucma->sydymsk) {
Packit 9c3e7e
				ucma->state = unicast_fsm(ucma->state,
Packit 9c3e7e
							  UC_EV_GRANT_SYDY);
Packit 9c3e7e
			}
Packit 9c3e7e
			unicast_client_set_renewal(p, ucma, g->durationField);
Packit 9c3e7e
			clock_sync_interval(p->clock, g->logInterMessagePeriod);
Packit 9c3e7e
			break;
Packit 9c3e7e
		}
Packit 9c3e7e
		break;
Packit 9c3e7e
	case UC_HAVE_SYDY:
Packit 9c3e7e
		switch (mtype) {
Packit 9c3e7e
		case ANNOUNCE:
Packit 9c3e7e
		case DELAY_RESP:
Packit 9c3e7e
		case SYNC:
Packit 9c3e7e
			unicast_client_set_renewal(p, ucma, g->durationField);
Packit 9c3e7e
			break;
Packit 9c3e7e
		}
Packit 9c3e7e
		break;
Packit 9c3e7e
	}
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int unicast_client_set_tmo(struct port *p)
Packit 9c3e7e
{
Packit 9c3e7e
	return set_tmo_log(p->fda.fd[FD_UNICAST_REQ_TIMER], 1,
Packit 9c3e7e
			   p->unicast_master_table->logQueryInterval);
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
void unicast_client_state_changed(struct port *p)
Packit 9c3e7e
{
Packit 9c3e7e
	struct unicast_master_address *ucma;
Packit 9c3e7e
	struct PortIdentity pid;
Packit 9c3e7e
Packit 9c3e7e
	if (!unicast_client_enabled(p)) {
Packit 9c3e7e
		return;
Packit 9c3e7e
	}
Packit 9c3e7e
	pid = clock_parent_identity(p->clock);
Packit 9c3e7e
Packit 9c3e7e
	STAILQ_FOREACH(ucma, &p->unicast_master_table->addrs, list) {
Packit 9c3e7e
		if (pid_eq(&ucma->portIdentity, &pid)) {
Packit 9c3e7e
			ucma->state = unicast_fsm(ucma->state, UC_EV_SELECTED);
Packit 9c3e7e
		} else {
Packit 9c3e7e
			ucma->state = unicast_fsm(ucma->state, UC_EV_UNSELECTED);
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
}
Packit 9c3e7e
Packit 9c3e7e
int unicast_client_timer(struct port *p)
Packit 9c3e7e
{
Packit 9c3e7e
	struct unicast_master_address *master;
Packit 9c3e7e
	int err = 0;
Packit 9c3e7e
Packit 9c3e7e
	STAILQ_FOREACH(master, &p->unicast_master_table->addrs, list) {
Packit 9c3e7e
		if (master->type != transport_type(p->trp)) {
Packit 9c3e7e
			continue;
Packit 9c3e7e
		}
Packit 9c3e7e
		switch (master->state) {
Packit 9c3e7e
		case UC_WAIT:
Packit 9c3e7e
			err = unicast_client_announce(p, master);
Packit 9c3e7e
			break;
Packit 9c3e7e
		case UC_HAVE_ANN:
Packit 9c3e7e
			err = unicast_client_renew(p, master);
Packit 9c3e7e
			break;
Packit 9c3e7e
		case UC_NEED_SYDY:
Packit 9c3e7e
			err = unicast_client_sydy(p, master);
Packit 9c3e7e
			break;
Packit 9c3e7e
		case UC_HAVE_SYDY:
Packit 9c3e7e
			err = unicast_client_renew(p, master);
Packit 9c3e7e
			break;
Packit 9c3e7e
		}
Packit 9c3e7e
		if (p->delayMechanism == DM_P2P) {
Packit 9c3e7e
			unicast_client_peer_renew(p);
Packit 9c3e7e
		}
Packit 9c3e7e
	}
Packit 9c3e7e
Packit 9c3e7e
	unicast_client_set_tmo(p);
Packit 9c3e7e
	return err;
Packit 9c3e7e
}