msg: Introduce method for appending multiple TLVs on transmit.

In order to support multiple TLVs, the transmit code must be able to
append one TLV after another.  This patch adds a method that checks
whether there is room, allocates the TLV descriptor, sets the buffer
pointer, and appends the descriptor to the list.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
master
Richard Cochran 2018-02-23 22:43:24 -08:00
parent 7fe69e7ba0
commit 4a8877f904
2 changed files with 90 additions and 0 deletions

74
msg.c
View File

@ -110,6 +110,68 @@ static int hdr_pre_send(struct ptp_header *m)
return 0; return 0;
} }
static uint8_t *msg_suffix(struct ptp_message *m)
{
switch (msg_type(m)) {
case SYNC:
return NULL;
case DELAY_REQ:
return NULL;
case PDELAY_REQ:
return NULL;
case PDELAY_RESP:
return NULL;
case FOLLOW_UP:
return m->follow_up.suffix;
case DELAY_RESP:
return m->delay_resp.suffix;
case PDELAY_RESP_FOLLOW_UP:
return m->pdelay_resp_fup.suffix;
case ANNOUNCE:
return m->announce.suffix;
case SIGNALING:
return m->signaling.suffix;
case MANAGEMENT:
return m->management.suffix;
}
return NULL;
}
static struct tlv_extra *msg_tlv_prepare(struct ptp_message *msg, int length)
{
struct tlv_extra *extra, *tmp;
uint8_t *ptr;
/* Make sure this message type admits appended TLVs. */
ptr = msg_suffix(msg);
if (!ptr) {
pr_err("TLV on %s not allowed", msg_type_string(msg_type(msg)));
return NULL;
}
tmp = TAILQ_LAST(&msg->tlv_list, tlv_list);
if (tmp) {
ptr = (uint8_t *) tmp->tlv;
ptr += tmp->tlv->length;
}
/* Check that the message buffer has enough room for the new TLV. */
if ((unsigned long)(ptr + length) >
(unsigned long)(&msg->tail_room)) {
pr_debug("cannot fit TLV of length %d into message", length);
return NULL;
}
/* Allocate a TLV descriptor and setup the pointer. */
extra = tlv_extra_alloc();
if (!extra) {
pr_err("failed to allocate TLV descriptor");
return NULL;
}
extra->tlv = (struct TLV *) ptr;
return extra;
}
static void port_id_post_recv(struct PortIdentity *pid) static void port_id_post_recv(struct PortIdentity *pid)
{ {
pid->portNumber = ntohs(pid->portNumber); pid->portNumber = ntohs(pid->portNumber);
@ -395,6 +457,18 @@ int msg_pre_send(struct ptp_message *m)
return 0; return 0;
} }
struct tlv_extra *msg_tlv_append(struct ptp_message *msg, int length)
{
struct tlv_extra *extra;
extra = msg_tlv_prepare(msg, length);
if (extra) {
msg->header.messageLength += length;
msg_tlv_attach(msg, extra);
}
return extra;
}
void msg_tlv_attach(struct ptp_message *msg, struct tlv_extra *extra) void msg_tlv_attach(struct ptp_message *msg, struct tlv_extra *extra)
{ {
TAILQ_INSERT_TAIL(&msg->tlv_list, extra, list); TAILQ_INSERT_TAIL(&msg->tlv_list, extra, list);

16
msg.h
View File

@ -258,6 +258,22 @@ static inline Boolean field_is_set(struct ptp_message *m, int index, Octet bit)
return m->header.flagField[index] & bit ? TRUE : FALSE; return m->header.flagField[index] & bit ? TRUE : FALSE;
} }
/**
* Append a new TLV onto a message for transmission.
*
* This is a high level API designed for the transmit path. The
* function allocates a new descriptor, initializes its .tlv field,
* and ensures that the TLV will fit into the message buffer. This
* function increments the message length field by 'length' before
* returning.
*
* @param msg A message obtained using msg_allocate(). At a mininum,
* the message type and length fields must set by the caller.
* @param length The length of the TLV to append.
* @return A pointer to a TLV descriptor on success or NULL otherwise.
*/
struct tlv_extra *msg_tlv_append(struct ptp_message *msg, int length);
/** /**
* Place a TLV descriptor into a message's list of TLVs. * Place a TLV descriptor into a message's list of TLVs.
* *