avb: don't include ethernet header in in packets

Move vlan_id and prio to the stream.
This commit is contained in:
Wim Taymans 2022-04-07 15:14:45 +02:00
parent dec2bdf241
commit 9bfb23f3f8
16 changed files with 217 additions and 174 deletions

View file

@ -65,20 +65,8 @@ stream.properties = {
avb.properties = { avb.properties = {
# the addresses this server listens on # the addresses this server listens on
#ifname = "eth0.2"
ifname = "enp3s0" ifname = "enp3s0"
server.address = [
"unix:native"
#"unix:/tmp/something" # absolute paths may be used
#"tcp:4713" # IPv4 and IPv6 on all addresses
#"tcp:[::]:9999" # IPv6 on all addresses
#"tcp:127.0.0.1:8888" # IPv4 on a single address
#
#{ address = "tcp:4713" # address
# max-clients = 64 # maximum number of clients
# listen-backlog = 32 # backlog in the server listen queue
# client.access = "restricted" # permissions for clients
#}
]
# These overrides are only applied when running in a vm. # These overrides are only applied when running in a vm.
vm.overrides = { vm.overrides = {
} }

View file

@ -26,7 +26,6 @@
#define AVB_AAF_H #define AVB_AAF_H
struct avb_packet_aaf { struct avb_packet_aaf {
struct avb_ethernet_header hdr;
uint8_t subtype; uint8_t subtype;
#if __BYTE_ORDER == __BIG_ENDIAN #if __BYTE_ORDER == __BIG_ENDIAN
unsigned sv:1; unsigned sv:1;

View file

@ -57,21 +57,25 @@ struct acmp {
}; };
static void *pending_new(struct acmp *acmp, uint32_t type, uint64_t now, uint32_t timeout_ms, static void *pending_new(struct acmp *acmp, uint32_t type, uint64_t now, uint32_t timeout_ms,
const struct avb_packet_acmp *m, size_t size) const void *m, size_t size)
{ {
struct pending *p; struct pending *p;
struct avb_ethernet_header *h;
struct avb_packet_acmp *pm; struct avb_packet_acmp *pm;
p = calloc(1, sizeof(*p) + size); p = calloc(1, sizeof(*p) + size);
if (p == NULL) if (p == NULL)
return NULL; return NULL;
p->last_time = now; p->last_time = now;
p->timeout = timeout_ms * SPA_NSEC_PER_MSEC; p->timeout = timeout_ms * SPA_NSEC_PER_MSEC;
p->old_sequence_id = ntohs(m->sequence_id);
p->sequence_id = acmp->sequence_id[type]++; p->sequence_id = acmp->sequence_id[type]++;
p->size = size; p->size = size;
p->ptr = SPA_PTROFF(p, sizeof(*p), void); p->ptr = SPA_PTROFF(p, sizeof(*p), void);
memcpy(p->ptr, m, size); memcpy(p->ptr, m, size);
pm = p->ptr;
h = p->ptr;
pm = SPA_PTROFF(h, sizeof(*h), void);
p->old_sequence_id = ntohs(pm->sequence_id);
pm->sequence_id = htons(p->sequence_id); pm->sequence_id = htons(p->sequence_id);
spa_list_append(&acmp->pending[type], &p->link); spa_list_append(&acmp->pending[type], &p->link);
@ -103,39 +107,39 @@ static int reply_not_supported(struct acmp *acmp, uint8_t type, const void *m, i
{ {
struct server *server = acmp->server; struct server *server = acmp->server;
uint8_t buf[len]; uint8_t buf[len];
struct avb_packet_acmp *reply = (struct avb_packet_acmp*)buf; struct avb_ethernet_header *h = (void*)buf;
struct avb_packet_acmp *reply = SPA_PTROFF(h, sizeof(*h), void);
memcpy(reply, m, len); memcpy(h, m, len);
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, type); AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, type);
AVB_PACKET_ACMP_SET_STATUS(reply, AVB_ACMP_STATUS_NOT_SUPPORTED); AVB_PACKET_ACMP_SET_STATUS(reply, AVB_ACMP_STATUS_NOT_SUPPORTED);
return avb_server_send_packet(server, reply->hdr.eth.src, return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, len);
AVB_TSN_ETH, reply, len);
} }
static int retry_pending(struct acmp *acmp, uint64_t now, struct pending *p) static int retry_pending(struct acmp *acmp, uint64_t now, struct pending *p)
{ {
struct server *server = acmp->server; struct server *server = acmp->server;
struct avb_packet_acmp *cmd = p->ptr; struct avb_ethernet_header *h = p->ptr;
p->retry++; p->retry++;
p->last_time = now; p->last_time = now;
return avb_server_send_packet(server, cmd->hdr.eth.dest, return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, p->ptr, p->size);
AVB_TSN_ETH, cmd, p->size);
} }
static int handle_connect_tx_command(struct acmp *acmp, uint64_t now, const void *m, int len) static int handle_connect_tx_command(struct acmp *acmp, uint64_t now, const void *m, int len)
{ {
struct server *server = acmp->server; struct server *server = acmp->server;
uint8_t buf[len]; uint8_t buf[len];
const struct avb_packet_acmp *p = m; struct avb_ethernet_header *h = (void*)buf;
struct avb_packet_acmp *reply = (struct avb_packet_acmp*)buf; struct avb_packet_acmp *reply = SPA_PTROFF(h, sizeof(*h), void);
const struct avb_packet_acmp *p = SPA_PTROFF(m, sizeof(*h), void);
int status = AVB_ACMP_STATUS_SUCCESS; int status = AVB_ACMP_STATUS_SUCCESS;
struct stream *stream; struct stream *stream;
if (be64toh(p->talker_guid) != server->entity_id) if (be64toh(p->talker_guid) != server->entity_id)
return 0; return 0;
memcpy(reply, m, len); memcpy(buf, m, len);
stream = server_find_stream(server, SPA_DIRECTION_OUTPUT, stream = server_find_stream(server, SPA_DIRECTION_OUTPUT,
reply->talker_unique_id); reply->talker_unique_id);
if (stream == NULL) { if (stream == NULL) {
@ -150,18 +154,18 @@ static int handle_connect_tx_command(struct acmp *acmp, uint64_t now, const void
memcpy(reply->stream_dest_mac, stream->addr, 6); memcpy(reply->stream_dest_mac, stream->addr, 6);
reply->connection_count = htons(1); reply->connection_count = htons(1);
reply->stream_vlan_id = htons(2); reply->stream_vlan_id = htons(stream->vlan_id);
done: done:
AVB_PACKET_ACMP_SET_STATUS(reply, status); AVB_PACKET_ACMP_SET_STATUS(reply, status);
return avb_server_send_packet(server, reply->hdr.eth.dest, return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, buf, len);
AVB_TSN_ETH, reply, len);
} }
static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const void *m, int len) static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const void *m, int len)
{ {
struct server *server = acmp->server; struct server *server = acmp->server;
const struct avb_packet_acmp *resp = m; struct avb_ethernet_header *h;
const struct avb_packet_acmp *resp = SPA_PTROFF(m, sizeof(*h), void);
struct avb_packet_acmp *reply; struct avb_packet_acmp *reply;
struct pending *pending; struct pending *pending;
uint16_t sequence_id; uint16_t sequence_id;
@ -177,13 +181,16 @@ static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const voi
if (pending == NULL) if (pending == NULL)
return 0; return 0;
reply = pending->ptr; h = pending->ptr;
memcpy(reply, resp, SPA_MIN((int)pending->size, len)); pending->size = SPA_MIN((int)pending->size, len);
memcpy(h, m, pending->size);
reply = SPA_PTROFF(h, sizeof(*h), void);
reply->sequence_id = htons(pending->old_sequence_id); reply->sequence_id = htons(pending->old_sequence_id);
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE); AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE);
stream = server_find_stream(server, SPA_DIRECTION_INPUT, stream = server_find_stream(server, SPA_DIRECTION_INPUT,
reply->listener_unique_id); ntohs(reply->listener_unique_id));
if (stream == NULL) if (stream == NULL)
return 0; return 0;
@ -191,8 +198,7 @@ static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const voi
memcpy(stream->addr, reply->stream_dest_mac, 6); memcpy(stream->addr, reply->stream_dest_mac, 6);
stream_activate(stream, now); stream_activate(stream, now);
res = avb_server_send_packet(server, reply->hdr.eth.dest, res = avb_server_send_packet(server, h->dest, AVB_TSN_ETH, h, pending->size);
AVB_TSN_ETH, reply, pending->size);
pending_free(acmp, pending); pending_free(acmp, pending);
@ -203,15 +209,16 @@ static int handle_disconnect_tx_command(struct acmp *acmp, uint64_t now, const v
{ {
struct server *server = acmp->server; struct server *server = acmp->server;
uint8_t buf[len]; uint8_t buf[len];
const struct avb_packet_acmp *p = m; struct avb_ethernet_header *h = (void*)buf;
struct avb_packet_acmp *reply = (struct avb_packet_acmp*)buf; struct avb_packet_acmp *reply = SPA_PTROFF(h, sizeof(*h), void);
const struct avb_packet_acmp *p = SPA_PTROFF(m, sizeof(*h), void);
int status = AVB_ACMP_STATUS_SUCCESS; int status = AVB_ACMP_STATUS_SUCCESS;
struct stream *stream; struct stream *stream;
if (be64toh(p->talker_guid) != server->entity_id) if (be64toh(p->talker_guid) != server->entity_id)
return 0; return 0;
memcpy(reply, m, len); memcpy(buf, m, len);
stream = server_find_stream(server, SPA_DIRECTION_OUTPUT, stream = server_find_stream(server, SPA_DIRECTION_OUTPUT,
reply->talker_unique_id); reply->talker_unique_id);
if (stream == NULL) { if (stream == NULL) {
@ -225,15 +232,15 @@ static int handle_disconnect_tx_command(struct acmp *acmp, uint64_t now, const v
done: done:
AVB_PACKET_ACMP_SET_STATUS(reply, status); AVB_PACKET_ACMP_SET_STATUS(reply, status);
return avb_server_send_packet(server, reply->hdr.eth.dest, return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, buf, len);
AVB_TSN_ETH, reply, len);
} }
static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const void *m, int len) static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const void *m, int len)
{ {
struct server *server = acmp->server; struct server *server = acmp->server;
const struct avb_packet_acmp *resp = m; struct avb_ethernet_header *h;
struct avb_packet_acmp *reply; struct avb_packet_acmp *reply;
const struct avb_packet_acmp *resp = SPA_PTROFF(m, sizeof(*h), void);
struct pending *pending; struct pending *pending;
uint16_t sequence_id; uint16_t sequence_id;
struct stream *stream; struct stream *stream;
@ -248,8 +255,11 @@ static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const
if (pending == NULL) if (pending == NULL)
return 0; return 0;
reply = pending->ptr; h = pending->ptr;
memcpy(reply, resp, SPA_MIN((int)pending->size, len)); pending->size = SPA_MIN((int)pending->size, len);
memcpy(h, m, pending->size);
reply = SPA_PTROFF(h, sizeof(*h), void);
reply->sequence_id = htons(pending->old_sequence_id); reply->sequence_id = htons(pending->old_sequence_id);
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE); AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE);
@ -260,8 +270,7 @@ static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const
stream_deactivate(stream, now); stream_deactivate(stream, now);
res = avb_server_send_packet(server, reply->hdr.eth.dest, res = avb_server_send_packet(server, h->dest, AVB_TSN_ETH, h, pending->size);
AVB_TSN_ETH, reply, pending->size);
pending_free(acmp, pending); pending_free(acmp, pending);
@ -271,22 +280,23 @@ static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const
static int handle_connect_rx_command(struct acmp *acmp, uint64_t now, const void *m, int len) static int handle_connect_rx_command(struct acmp *acmp, uint64_t now, const void *m, int len)
{ {
struct server *server = acmp->server; struct server *server = acmp->server;
const struct avb_packet_acmp *p = m; struct avb_ethernet_header *h;
const struct avb_packet_acmp *p = SPA_PTROFF(m, sizeof(*h), void);
struct avb_packet_acmp *cmd; struct avb_packet_acmp *cmd;
if (be64toh(p->listener_guid) != server->entity_id) if (be64toh(p->listener_guid) != server->entity_id)
return 0; return 0;
cmd = pending_new(acmp, PENDING_TALKER, now, h = pending_new(acmp, PENDING_TALKER, now,
AVB_ACMP_TIMEOUT_CONNECT_TX_COMMAND_MS, m, len); AVB_ACMP_TIMEOUT_CONNECT_TX_COMMAND_MS, m, len);
if (cmd == NULL) if (h == NULL)
return -errno; return -errno;
cmd = SPA_PTROFF(h, sizeof(*h), void);
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(cmd, AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND); AVB_PACKET_ACMP_SET_MESSAGE_TYPE(cmd, AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND);
AVB_PACKET_ACMP_SET_STATUS(cmd, AVB_ACMP_STATUS_SUCCESS); AVB_PACKET_ACMP_SET_STATUS(cmd, AVB_ACMP_STATUS_SUCCESS);
return avb_server_send_packet(server, cmd->hdr.eth.dest, return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, h, len);
AVB_TSN_ETH, cmd, len);
} }
static int handle_ignore(struct acmp *acmp, uint64_t now, const void *m, int len) static int handle_ignore(struct acmp *acmp, uint64_t now, const void *m, int len)
@ -297,22 +307,23 @@ static int handle_ignore(struct acmp *acmp, uint64_t now, const void *m, int len
static int handle_disconnect_rx_command(struct acmp *acmp, uint64_t now, const void *m, int len) static int handle_disconnect_rx_command(struct acmp *acmp, uint64_t now, const void *m, int len)
{ {
struct server *server = acmp->server; struct server *server = acmp->server;
const struct avb_packet_acmp *p = m; struct avb_ethernet_header *h;
const struct avb_packet_acmp *p = SPA_PTROFF(m, sizeof(*h), void);
struct avb_packet_acmp *cmd; struct avb_packet_acmp *cmd;
if (be64toh(p->listener_guid) != server->entity_id) if (be64toh(p->listener_guid) != server->entity_id)
return 0; return 0;
cmd = pending_new(acmp, PENDING_TALKER, now, h = pending_new(acmp, PENDING_TALKER, now,
AVB_ACMP_TIMEOUT_DISCONNECT_TX_COMMAND_MS, m, len); AVB_ACMP_TIMEOUT_DISCONNECT_TX_COMMAND_MS, m, len);
if (cmd == NULL) if (h == NULL)
return -errno; return -errno;
cmd = SPA_PTROFF(h, sizeof(*h), void);
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(cmd, AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND); AVB_PACKET_ACMP_SET_MESSAGE_TYPE(cmd, AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND);
AVB_PACKET_ACMP_SET_STATUS(cmd, AVB_ACMP_STATUS_SUCCESS); AVB_PACKET_ACMP_SET_STATUS(cmd, AVB_ACMP_STATUS_SUCCESS);
return avb_server_send_packet(server, cmd->hdr.eth.dest, return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, h, len);
AVB_TSN_ETH, cmd, len);
} }
static const struct msg_info msg_info[] = { static const struct msg_info msg_info[] = {
@ -347,14 +358,15 @@ static int acmp_message(void *data, uint64_t now, const void *message, int len)
{ {
struct acmp *acmp = data; struct acmp *acmp = data;
struct server *server = acmp->server; struct server *server = acmp->server;
const struct avb_packet_acmp *p = message; const struct avb_ethernet_header *h = message;
const struct avb_packet_acmp *p = SPA_PTROFF(h, sizeof(*h), void);
const struct msg_info *info; const struct msg_info *info;
int message_type; int message_type;
if (ntohs(p->hdr.eth.type) != AVB_TSN_ETH) if (ntohs(h->type) != AVB_TSN_ETH)
return 0; return 0;
if (memcmp(p->hdr.eth.dest, mac, 6) != 0 && if (memcmp(h->dest, mac, 6) != 0 &&
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0) memcmp(h->dest, server->mac_addr, 6) != 0)
return 0; return 0;
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_ACMP) if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_ACMP)
@ -369,9 +381,9 @@ static int acmp_message(void *data, uint64_t now, const void *message, int len)
pw_log_info("got ACMP message %s", info->name); pw_log_info("got ACMP message %s", info->name);
if (info->handle == NULL) if (info->handle == NULL)
return reply_not_supported(acmp, message_type | 1, p, len); return reply_not_supported(acmp, message_type | 1, message, len);
return info->handle(acmp, now, p, len); return info->handle(acmp, now, message, len);
} }
static void acmp_destroy(void *data) static void acmp_destroy(void *data)

View file

@ -35,9 +35,12 @@ static const uint8_t mac[6] = AVB_BROADCAST_MAC;
struct entity { struct entity {
struct spa_list link; struct spa_list link;
struct avb_packet_adp packet; uint64_t entity_id;
uint64_t last_time; uint64_t last_time;
int valid_time;
unsigned advertise:1; unsigned advertise:1;
size_t len;
uint8_t buf[128];
}; };
struct adp { struct adp {
@ -52,7 +55,7 @@ static struct entity *find_entity_by_id(struct adp *adp, uint64_t id)
{ {
struct entity *e; struct entity *e;
spa_list_for_each(e, &adp->entities, link) spa_list_for_each(e, &adp->entities, link)
if (be64toh(e->packet.entity_id) == id) if (e->entity_id == id)
return e; return e;
return NULL; return NULL;
} }
@ -64,31 +67,41 @@ static void entity_free(struct entity *e)
static int send_departing(struct adp *adp, uint64_t now, struct entity *e) static int send_departing(struct adp *adp, uint64_t now, struct entity *e)
{ {
AVB_PACKET_ADP_SET_MESSAGE_TYPE(&e->packet, AVB_ADP_MESSAGE_TYPE_ENTITY_DEPARTING); struct avb_ethernet_header *h = (void*)e->buf;
e->packet.available_index = htonl(adp->available_index++); struct avb_packet_adp *p = SPA_PTROFF(h, sizeof(*h), void);
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, &e->packet, sizeof(e->packet));
AVB_PACKET_ADP_SET_MESSAGE_TYPE(p, AVB_ADP_MESSAGE_TYPE_ENTITY_DEPARTING);
p->available_index = htonl(adp->available_index++);
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, e->buf, e->len);
e->last_time = now; e->last_time = now;
return 0; return 0;
} }
static int send_advertise(struct adp *adp, uint64_t now, struct entity *e) static int send_advertise(struct adp *adp, uint64_t now, struct entity *e)
{ {
AVB_PACKET_ADP_SET_MESSAGE_TYPE(&e->packet, AVB_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE); struct avb_ethernet_header *h = (void*)e->buf;
e->packet.available_index = htonl(adp->available_index++); struct avb_packet_adp *p = SPA_PTROFF(h, sizeof(*h), void);
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, &e->packet, sizeof(e->packet));
AVB_PACKET_ADP_SET_MESSAGE_TYPE(p, AVB_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE);
p->available_index = htonl(adp->available_index++);
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, e->buf, e->len);
e->last_time = now; e->last_time = now;
return 0; return 0;
} }
static int send_discover(struct adp *adp, uint64_t entity_id) static int send_discover(struct adp *adp, uint64_t entity_id)
{ {
struct avb_packet_adp p; uint8_t buf[128];
spa_zero(p); struct avb_ethernet_header *h = (void*)buf;
AVB_PACKET_SET_SUBTYPE(&p.hdr, AVB_SUBTYPE_ADP); struct avb_packet_adp *p = SPA_PTROFF(h, sizeof(*h), void);
AVB_PACKET_SET_LENGTH(&p.hdr, AVB_ADP_CONTROL_DATA_LENGTH); size_t len = sizeof(*h) + sizeof(*p);
AVB_PACKET_ADP_SET_MESSAGE_TYPE(&p, AVB_ADP_MESSAGE_TYPE_ENTITY_DISCOVER);
p.entity_id = htonl(entity_id); spa_memzero(buf, sizeof(buf));
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, &p, sizeof(p)); AVB_PACKET_SET_SUBTYPE(&p->hdr, AVB_SUBTYPE_ADP);
AVB_PACKET_SET_LENGTH(&p->hdr, AVB_ADP_CONTROL_DATA_LENGTH);
AVB_PACKET_ADP_SET_MESSAGE_TYPE(p, AVB_ADP_MESSAGE_TYPE_ENTITY_DISCOVER);
p->entity_id = htonl(entity_id);
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, buf, len);
return 0; return 0;
} }
@ -96,16 +109,17 @@ static int adp_message(void *data, uint64_t now, const void *message, int len)
{ {
struct adp *adp = data; struct adp *adp = data;
struct server *server = adp->server; struct server *server = adp->server;
const struct avb_packet_adp *p = message; const struct avb_ethernet_header *h = message;
const struct avb_packet_adp *p = SPA_PTROFF(h, sizeof(*h), void);
struct entity *e; struct entity *e;
int message_type; int message_type;
char buf[128]; char buf[128];
uint64_t entity_id; uint64_t entity_id;
if (ntohs(p->hdr.eth.type) != AVB_TSN_ETH) if (ntohs(h->type) != AVB_TSN_ETH)
return 0; return 0;
if (memcmp(p->hdr.eth.dest, mac, 6) != 0 && if (memcmp(h->dest, mac, 6) != 0 &&
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0) memcmp(h->dest, server->mac_addr, 6) != 0)
return 0; return 0;
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_ADP || if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_ADP ||
@ -124,7 +138,10 @@ static int adp_message(void *data, uint64_t now, const void *message, int len)
if (e == NULL) if (e == NULL)
return -errno; return -errno;
e->packet = *p; memcpy(e->buf, message, len);
e->len = len;
e->valid_time = AVB_PACKET_ADP_GET_VALID_TIME(p);
e->entity_id = entity_id;
spa_list_append(&adp->entities, &e->link); spa_list_append(&adp->entities, &e->link);
pw_log_info("entity %s available", pw_log_info("entity %s available",
avb_utils_format_id(buf, sizeof(buf), entity_id)); avb_utils_format_id(buf, sizeof(buf), entity_id));
@ -145,8 +162,8 @@ static int adp_message(void *data, uint64_t now, const void *message, int len)
spa_list_for_each(e, &adp->entities, link) spa_list_for_each(e, &adp->entities, link)
if (e->advertise) if (e->advertise)
send_advertise(adp, now, e); send_advertise(adp, now, e);
} else if (e != NULL && e->advertise && } else if (e != NULL &&
be64toh(e->packet.entity_id) == entity_id) { e->advertise && e->entity_id == entity_id) {
send_advertise(adp, now, e); send_advertise(adp, now, e);
} }
break; break;
@ -169,14 +186,11 @@ static void check_timeout(struct adp *adp, uint64_t now)
char buf[128]; char buf[128];
spa_list_for_each_safe(e, t, &adp->entities, link) { spa_list_for_each_safe(e, t, &adp->entities, link) {
int valid_time = AVB_PACKET_ADP_GET_VALID_TIME(&e->packet); if (e->last_time + (e->valid_time + 2) * SPA_NSEC_PER_SEC > now)
if (e->last_time + (valid_time + 2) * SPA_NSEC_PER_SEC > now)
continue; continue;
pw_log_info("entity %s timeout", pw_log_info("entity %s timeout",
avb_utils_format_id(buf, sizeof(buf), avb_utils_format_id(buf, sizeof(buf), e->entity_id));
be64toh(e->packet.entity_id)));
if (e->advertise) if (e->advertise)
send_departing(adp, now, e); send_departing(adp, now, e);
@ -186,18 +200,16 @@ static void check_timeout(struct adp *adp, uint64_t now)
} }
static void check_readvertize(struct adp *adp, uint64_t now, struct entity *e) static void check_readvertize(struct adp *adp, uint64_t now, struct entity *e)
{ {
int valid_time = AVB_PACKET_ADP_GET_VALID_TIME(&e->packet);
char buf[128]; char buf[128];
if (!e->advertise) if (!e->advertise)
return; return;
if (e->last_time + (valid_time / 2) * SPA_NSEC_PER_SEC > now) if (e->last_time + (e->valid_time / 2) * SPA_NSEC_PER_SEC > now)
return; return;
pw_log_debug("entity %s readvertise", pw_log_debug("entity %s readvertise",
avb_utils_format_id(buf, sizeof(buf), avb_utils_format_id(buf, sizeof(buf), e->entity_id));
be64toh(e->packet.entity_id)));
send_advertise(adp, now, e); send_advertise(adp, now, e);
} }
@ -210,6 +222,7 @@ static int check_advertise(struct adp *adp, uint64_t now)
struct avb_aem_desc_avb_interface *avb_interface; struct avb_aem_desc_avb_interface *avb_interface;
struct entity *e; struct entity *e;
uint64_t entity_id; uint64_t entity_id;
struct avb_ethernet_header *h;
struct avb_packet_adp *p; struct avb_packet_adp *p;
char buf[128]; char buf[128];
@ -237,13 +250,17 @@ static int check_advertise(struct adp *adp, uint64_t now)
return -errno; return -errno;
e->advertise = true; e->advertise = true;
e->valid_time = 10;
e->last_time = now; e->last_time = now;
e->entity_id = entity_id;
e->len = sizeof(*h) + sizeof(*p);
p = &e->packet; h = (void*)e->buf;
p = SPA_PTROFF(h, sizeof(*h), void);
AVB_PACKET_SET_LENGTH(&p->hdr, AVB_ADP_CONTROL_DATA_LENGTH); AVB_PACKET_SET_LENGTH(&p->hdr, AVB_ADP_CONTROL_DATA_LENGTH);
AVB_PACKET_SET_SUBTYPE(&p->hdr, AVB_SUBTYPE_ADP); AVB_PACKET_SET_SUBTYPE(&p->hdr, AVB_SUBTYPE_ADP);
AVB_PACKET_ADP_SET_MESSAGE_TYPE(p, AVB_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE); AVB_PACKET_ADP_SET_MESSAGE_TYPE(p, AVB_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE);
AVB_PACKET_ADP_SET_VALID_TIME(p, 10); AVB_PACKET_ADP_SET_VALID_TIME(p, e->valid_time);
p->entity_id = entity->entity_id; p->entity_id = entity->entity_id;
p->entity_model_id = entity->entity_model_id; p->entity_model_id = entity->entity_model_id;

View file

@ -29,14 +29,14 @@ static int reply_status(struct aecp *aecp, int status, const void *m, int len)
{ {
struct server *server = aecp->server; struct server *server = aecp->server;
uint8_t buf[len]; uint8_t buf[len];
struct avb_packet_aecp_header *reply = (struct avb_packet_aecp_header*)buf; struct avb_ethernet_header *h = (void*)buf;
struct avb_packet_aecp_header *reply = SPA_PTROFF(h, sizeof(*h), void);
memcpy(reply, m, len); memcpy(buf, m, len);
AVB_PACKET_AECP_SET_MESSAGE_TYPE(reply, AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE); AVB_PACKET_AECP_SET_MESSAGE_TYPE(reply, AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE);
AVB_PACKET_AECP_SET_STATUS(reply, status); AVB_PACKET_AECP_SET_STATUS(reply, status);
return avb_server_send_packet(server, reply->hdr.eth.src, return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, len);
AVB_TSN_ETH, reply, len);
} }
static int reply_not_implemented(struct aecp *aecp, const void *m, int len) static int reply_not_implemented(struct aecp *aecp, const void *m, int len)
@ -101,7 +101,8 @@ static int handle_lock_entity(struct aecp *aecp, const void *m, int len)
static int handle_read_descriptor(struct aecp *aecp, const void *m, int len) static int handle_read_descriptor(struct aecp *aecp, const void *m, int len)
{ {
struct server *server = aecp->server; struct server *server = aecp->server;
const struct avb_packet_aecp_aem *p = m; const struct avb_ethernet_header *h = m;
const struct avb_packet_aecp_aem *p = SPA_PTROFF(h, sizeof(*h), void);
struct avb_packet_aecp_aem *reply; struct avb_packet_aecp_aem *reply;
const struct avb_packet_aecp_aem_read_descriptor *rd; const struct avb_packet_aecp_aem_read_descriptor *rd;
uint16_t desc_type, desc_id; uint16_t desc_type, desc_id;
@ -118,31 +119,32 @@ static int handle_read_descriptor(struct aecp *aecp, const void *m, int len)
desc = server_find_descriptor(server, desc_type, desc_id); desc = server_find_descriptor(server, desc_type, desc_id);
if (desc == NULL) if (desc == NULL)
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len); return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
memcpy(buf, p, len); memcpy(buf, m, len);
psize = sizeof(*rd); psize = sizeof(*rd);
size = sizeof(*reply) + psize; size = sizeof(*h) + sizeof(*reply) + psize;
memcpy(buf + size, desc->ptr, desc->size); memcpy(buf + size, desc->ptr, desc->size);
size += desc->size; size += desc->size;
psize += desc->size; psize += desc->size;
reply = (struct avb_packet_aecp_aem*)buf; h = (void*)buf;
reply = SPA_PTROFF(h, sizeof(*h), void);
AVB_PACKET_AECP_SET_MESSAGE_TYPE(&reply->aecp, AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE); AVB_PACKET_AECP_SET_MESSAGE_TYPE(&reply->aecp, AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE);
AVB_PACKET_AECP_SET_STATUS(&reply->aecp, AVB_AECP_AEM_STATUS_SUCCESS); AVB_PACKET_AECP_SET_STATUS(&reply->aecp, AVB_AECP_AEM_STATUS_SUCCESS);
AVB_PACKET_SET_LENGTH(&reply->aecp.hdr, psize + 12); AVB_PACKET_SET_LENGTH(&reply->aecp.hdr, psize + 12);
return avb_server_send_packet(server, reply->aecp.hdr.eth.src, return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, size);
AVB_TSN_ETH, reply, size);
} }
/* GET_AVB_INFO */ /* GET_AVB_INFO */
static int handle_get_avb_info(struct aecp *aecp, const void *m, int len) static int handle_get_avb_info(struct aecp *aecp, const void *m, int len)
{ {
struct server *server = aecp->server; struct server *server = aecp->server;
const struct avb_packet_aecp_aem *p = m; const struct avb_ethernet_header *h = m;
const struct avb_packet_aecp_aem *p = SPA_PTROFF(h, sizeof(*h), void);
struct avb_packet_aecp_aem *reply; struct avb_packet_aecp_aem *reply;
struct avb_packet_aecp_aem_get_avb_info *i; struct avb_packet_aecp_aem_get_avb_info *i;
struct avb_aem_desc_avb_interface *avb_interface; struct avb_aem_desc_avb_interface *avb_interface;
@ -158,19 +160,20 @@ static int handle_get_avb_info(struct aecp *aecp, const void *m, int len)
desc = server_find_descriptor(server, desc_type, desc_id); desc = server_find_descriptor(server, desc_type, desc_id);
if (desc == NULL) if (desc == NULL)
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len); return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
if (desc_type != AVB_AEM_DESC_AVB_INTERFACE || desc_id != 0) if (desc_type != AVB_AEM_DESC_AVB_INTERFACE || desc_id != 0)
return reply_not_implemented(aecp, m, len); return reply_not_implemented(aecp, m, len);
avb_interface = desc->ptr; avb_interface = desc->ptr;
memcpy(buf, p, len); memcpy(buf, m, len);
psize = sizeof(*i); psize = sizeof(*i);
size = sizeof(*reply) + psize; size = sizeof(*h) + sizeof(*reply) + psize;
reply = (struct avb_packet_aecp_aem *)buf; h = (void*)buf;
reply = SPA_PTROFF(h, sizeof(*h), void);
AVB_PACKET_AECP_SET_MESSAGE_TYPE(&reply->aecp, AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE); AVB_PACKET_AECP_SET_MESSAGE_TYPE(&reply->aecp, AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE);
AVB_PACKET_AECP_SET_STATUS(&reply->aecp, AVB_AECP_AEM_STATUS_SUCCESS); AVB_PACKET_AECP_SET_STATUS(&reply->aecp, AVB_AECP_AEM_STATUS_SUCCESS);
AVB_PACKET_SET_LENGTH(&reply->aecp.hdr, psize + 12); AVB_PACKET_SET_LENGTH(&reply->aecp.hdr, psize + 12);
@ -182,8 +185,7 @@ static int handle_get_avb_info(struct aecp *aecp, const void *m, int len)
i->flags = 0; i->flags = 0;
i->msrp_mappings_count = htons(0); i->msrp_mappings_count = htons(0);
return avb_server_send_packet(server, reply->aecp.hdr.eth.src, return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, size);
AVB_TSN_ETH, reply, size);
} }
/* AEM_COMMAND */ /* AEM_COMMAND */
@ -259,7 +261,8 @@ static inline const struct cmd_info *find_cmd_info(uint16_t type, const char *na
int avb_aecp_aem_handle_command(struct aecp *aecp, const void *m, int len) int avb_aecp_aem_handle_command(struct aecp *aecp, const void *m, int len)
{ {
const struct avb_packet_aecp_aem *p = m; const struct avb_ethernet_header *h = m;
const struct avb_packet_aecp_aem *p = SPA_PTROFF(h, sizeof(*h), void);
uint16_t cmd_type; uint16_t cmd_type;
const struct cmd_info *info; const struct cmd_info *info;

View file

@ -43,13 +43,13 @@ static int reply_not_implemented(struct aecp *aecp, const void *p, int len)
{ {
struct server *server = aecp->server; struct server *server = aecp->server;
uint8_t buf[len]; uint8_t buf[len];
struct avb_packet_aecp_header *reply = (struct avb_packet_aecp_header*)buf; struct avb_ethernet_header *h = (void*)buf;
struct avb_packet_aecp_header *reply = SPA_PTROFF(h, sizeof(*h), void);
memcpy(reply, p, len); memcpy(h, p, len);
AVB_PACKET_AECP_SET_STATUS(reply, AVB_AECP_STATUS_NOT_IMPLEMENTED); AVB_PACKET_AECP_SET_STATUS(reply, AVB_AECP_STATUS_NOT_IMPLEMENTED);
return avb_server_send_packet(server, reply->hdr.eth.src, return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, len);
AVB_TSN_ETH, reply, len);
} }
static const struct msg_info msg_info[] = { static const struct msg_info msg_info[] = {
@ -80,14 +80,15 @@ static int aecp_message(void *data, uint64_t now, const void *message, int len)
{ {
struct aecp *aecp = data; struct aecp *aecp = data;
struct server *server = aecp->server; struct server *server = aecp->server;
const struct avb_packet_aecp_header *p = message; const struct avb_ethernet_header *h = message;
const struct avb_packet_aecp_header *p = SPA_PTROFF(h, sizeof(*h), void);
const struct msg_info *info; const struct msg_info *info;
int message_type; int message_type;
if (ntohs(p->hdr.eth.type) != AVB_TSN_ETH) if (ntohs(h->type) != AVB_TSN_ETH)
return 0; return 0;
if (memcmp(p->hdr.eth.dest, mac, 6) != 0 && if (memcmp(h->dest, mac, 6) != 0 &&
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0) memcmp(h->dest, server->mac_addr, 6) != 0)
return 0; return 0;
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_AECP) if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_AECP)
return 0; return 0;
@ -96,14 +97,14 @@ static int aecp_message(void *data, uint64_t now, const void *message, int len)
info = find_msg_info(message_type, NULL); info = find_msg_info(message_type, NULL);
if (info == NULL) if (info == NULL)
return reply_not_implemented(aecp, p, len); return reply_not_implemented(aecp, message, len);
pw_log_debug("got AECP message %s", info->name); pw_log_debug("got AECP message %s", info->name);
if (info->handle == NULL) if (info->handle == NULL)
return reply_not_implemented(aecp, p, len); return reply_not_implemented(aecp, message, len);
return info->handle(aecp, p, len); return info->handle(aecp, message, len);
} }
static void aecp_destroy(void *data) static void aecp_destroy(void *data)

View file

@ -79,7 +79,7 @@ struct pw_avb *pw_avb_new(struct pw_context *context,
spa_list_init(&impl->servers); spa_list_init(&impl->servers);
avdecc_server_new(impl, pw_properties_get(props, "ifname"), NULL); avdecc_server_new(impl, &props->dict);
return (struct pw_avb*)impl; return (struct pw_avb*)impl;

View file

@ -257,7 +257,7 @@ error_no_source:
return res; return res;
} }
struct server *avdecc_server_new(struct impl *impl, const char *ifname, struct spa_dict *props) struct server *avdecc_server_new(struct impl *impl, struct spa_dict *props)
{ {
struct server *server; struct server *server;
int res = 0; int res = 0;
@ -268,7 +268,7 @@ struct server *avdecc_server_new(struct impl *impl, const char *ifname, struct s
server->impl = impl; server->impl = impl;
spa_list_append(&impl->servers, &server->link); spa_list_append(&impl->servers, &server->link);
server->ifname = strdup(ifname); server->ifname = strdup(spa_dict_lookup(props, "ifname"));
spa_hook_list_init(&server->listener_list); spa_hook_list_init(&server->listener_list);
spa_list_init(&server->descriptors); spa_list_init(&server->descriptors);
spa_list_init(&server->streams); spa_list_init(&server->streams);
@ -294,9 +294,9 @@ struct server *avdecc_server_new(struct impl *impl, const char *ifname, struct s
server->domain_attr = avb_msrp_attribute_new(server->msrp, server->domain_attr = avb_msrp_attribute_new(server->msrp,
AVB_MSRP_ATTRIBUTE_TYPE_DOMAIN); AVB_MSRP_ATTRIBUTE_TYPE_DOMAIN);
server->domain_attr->attr.domain.sr_class_id = 6; server->domain_attr->attr.domain.sr_class_id = AVB_MSRP_CLASS_ID_DEFAULT;
server->domain_attr->attr.domain.sr_class_priority = 3; server->domain_attr->attr.domain.sr_class_priority = AVB_MSRP_PRIORITY_DEFAULT;
server->domain_attr->attr.domain.sr_class_vid = htons(2); server->domain_attr->attr.domain.sr_class_vid = htons(AVB_DEFAULT_VLAN);
avb_mrp_attribute_begin(server->domain_attr->mrp, 0); avb_mrp_attribute_begin(server->domain_attr->mrp, 0);
avb_mrp_attribute_join(server->domain_attr->mrp, 0, true); avb_mrp_attribute_join(server->domain_attr->mrp, 0, true);

View file

@ -28,8 +28,6 @@
#include "packets.h" #include "packets.h"
struct avb_packet_iec61883 { struct avb_packet_iec61883 {
struct avb_ethernet_header eth;
uint32_t vlan;
uint8_t subtype; uint8_t subtype;
#if __BYTE_ORDER == __BIG_ENDIAN #if __BYTE_ORDER == __BIG_ENDIAN
unsigned sv:1; unsigned sv:1;

View file

@ -143,7 +143,7 @@ static inline struct stream *server_find_stream(struct server *server,
return NULL; return NULL;
} }
struct server *avdecc_server_new(struct impl *impl, const char *ifname, struct spa_dict *props); struct server *avdecc_server_new(struct impl *impl, struct spa_dict *props);
void avdecc_server_free(struct server *server); void avdecc_server_free(struct server *server);
void avdecc_server_add_listener(struct server *server, struct spa_hook *listener, void avdecc_server_add_listener(struct server *server, struct spa_hook *listener,

View file

@ -148,37 +148,43 @@ static uint16_t maap_check_conflict(struct maap *maap, const uint8_t request_sta
static int send_packet(struct maap *maap, uint64_t now, static int send_packet(struct maap *maap, uint64_t now,
uint8_t type, const uint8_t conflict_start[6], uint16_t conflict_count) uint8_t type, const uint8_t conflict_start[6], uint16_t conflict_count)
{ {
struct avb_packet_maap p; struct avb_ethernet_header *h;
struct avb_packet_maap *p;
uint8_t buf[1024];
uint8_t bmac[6] = AVB_MAAP_MAC; uint8_t bmac[6] = AVB_MAAP_MAC;
int res = 0; int res = 0;
uint8_t start[6]; uint8_t start[6];
spa_zero(p); spa_memzero(buf, sizeof(buf));
memcpy(p.hdr.eth.dest, bmac, 6); h = (void*)buf;
memcpy(p.hdr.eth.src, maap->server->mac_addr, 6); p = SPA_PTROFF(h, sizeof(*h), void);
p.hdr.eth.type = htons(AVB_TSN_ETH);
p.hdr.subtype = AVB_SUBTYPE_MAAP;
AVB_PACKET_SET_LENGTH(&p.hdr, sizeof(p) - sizeof(p.hdr.eth));
AVB_PACKET_MAAP_SET_MAAP_VERSION(&p, 1); memcpy(h->dest, bmac, 6);
AVB_PACKET_MAAP_SET_MESSAGE_TYPE(&p, type); memcpy(h->src, maap->server->mac_addr, 6);
h->type = htons(AVB_TSN_ETH);
p->hdr.subtype = AVB_SUBTYPE_MAAP;
AVB_PACKET_SET_LENGTH(&p->hdr, sizeof(*p));
AVB_PACKET_MAAP_SET_MAAP_VERSION(p, 1);
AVB_PACKET_MAAP_SET_MESSAGE_TYPE(p, type);
memcpy(start, maap_base, 4); memcpy(start, maap_base, 4);
start[4] = maap->offset >> 8; start[4] = maap->offset >> 8;
start[5] = maap->offset; start[5] = maap->offset;
AVB_PACKET_MAAP_SET_REQUEST_START(&p, start); AVB_PACKET_MAAP_SET_REQUEST_START(p, start);
AVB_PACKET_MAAP_SET_REQUEST_COUNT(&p, maap->count); AVB_PACKET_MAAP_SET_REQUEST_COUNT(p, maap->count);
if (conflict_count) { if (conflict_count) {
AVB_PACKET_MAAP_SET_CONFLICT_START(&p, conflict_start); AVB_PACKET_MAAP_SET_CONFLICT_START(p, conflict_start);
AVB_PACKET_MAAP_SET_CONFLICT_COUNT(&p, conflict_count); AVB_PACKET_MAAP_SET_CONFLICT_COUNT(p, conflict_count);
} }
if (maap->server->debug_messages) { if (maap->server->debug_messages) {
pw_log_info("send: %d (%s)", type, message_type_as_string(type)); pw_log_info("send: %d (%s)", type, message_type_as_string(type));
maap_message_debug(maap, &p); maap_message_debug(maap, p);
} }
if (send(maap->source->fd, &p, sizeof(p), 0) < 0) { if (send(maap->source->fd, p, sizeof(*h) + sizeof(*p), 0) < 0) {
res = -errno; res = -errno;
pw_log_warn("got send error: %m"); pw_log_warn("got send error: %m");
} }

View file

@ -202,9 +202,9 @@ static int encode_listener(struct msrp *msrp, struct attr *a, void *m)
static void debug_msrp_domain(const struct avb_packet_msrp_domain *d) static void debug_msrp_domain(const struct avb_packet_msrp_domain *d)
{ {
pw_log_info("domain"); pw_log_info("domain");
pw_log_info(" %d", d->sr_class_id); pw_log_info(" id: %d", d->sr_class_id);
pw_log_info(" %d", d->sr_class_priority); pw_log_info(" prio: %d", d->sr_class_priority);
pw_log_info(" %d", ntohs(d->sr_class_vid)); pw_log_info(" vid: %d", ntohs(d->sr_class_vid));
} }
static void notify_domain(struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify) static void notify_domain(struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify)

View file

@ -98,6 +98,9 @@ struct avb_packet_msrp_listener {
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
/* domain discovery */ /* domain discovery */
#define AVB_MSRP_CLASS_ID_DEFAULT 6
#define AVB_DEFAULT_VLAN 2
struct avb_packet_msrp_domain { struct avb_packet_msrp_domain {
uint8_t sr_class_id; uint8_t sr_class_id;
uint8_t sr_class_priority; uint8_t sr_class_priority;

View file

@ -54,8 +54,15 @@ struct avb_ethernet_header {
uint16_t type; uint16_t type;
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct avb_frame_header {
uint8_t dest[6];
uint8_t src[6];
uint16_t type; /* 802.1Q Virtual Lan 0x8100 */
uint16_t prio_cfi_id;
uint16_t etype;
} __attribute__ ((__packed__));
struct avb_packet_header { struct avb_packet_header {
struct avb_ethernet_header eth;
uint8_t subtype; uint8_t subtype;
#if __BYTE_ORDER == __BIG_ENDIAN #if __BYTE_ORDER == __BIG_ENDIAN
unsigned sv:1; /* stream_id valid */ unsigned sv:1; /* stream_id valid */

View file

@ -67,7 +67,7 @@ static void on_source_stream_process(void *data)
avail = spa_ringbuffer_get_read_index(&stream->ring, &index); avail = spa_ringbuffer_get_read_index(&stream->ring, &index);
if (avail < wanted) { if (avail < wanted) {
pw_log_warn("capture underrun %d < %d", avail, wanted); pw_log_debug("capture underrun %d < %d", avail, wanted);
memset(d[0].data, 0, n_bytes); memset(d[0].data, 0, n_bytes);
} else { } else {
spa_ringbuffer_read_data(&stream->ring, spa_ringbuffer_read_data(&stream->ring,
@ -110,7 +110,8 @@ static int flush_write(struct stream *stream, uint64_t current_time)
uint64_t ptime, txtime; uint64_t ptime, txtime;
int pdu_count; int pdu_count;
ssize_t n; ssize_t n;
struct avb_packet_iec61883 *p = (struct avb_packet_iec61883*)stream->pdu; struct avb_frame_header *h = (void*)stream->pdu;
struct avb_packet_iec61883 *p = SPA_PTROFF(h, sizeof(*h), void);
avail = spa_ringbuffer_get_read_index(&stream->ring, &index); avail = spa_ringbuffer_get_read_index(&stream->ring, &index);
@ -186,16 +187,21 @@ static void on_sink_stream_process(void *data)
static void setup_pdu(struct stream *stream) static void setup_pdu(struct stream *stream)
{ {
struct avb_packet_iec61883 *p = (struct avb_packet_iec61883*)stream->pdu; struct avb_frame_header *h;
struct avb_packet_iec61883 *p;
ssize_t payload_size, hdr_size, pdu_size; ssize_t payload_size, hdr_size, pdu_size;
hdr_size = sizeof(*p); spa_memzero(stream->pdu, sizeof(stream->pdu));
h = (struct avb_frame_header*)stream->pdu;
p = SPA_PTROFF(h, sizeof(*h), void);
hdr_size = sizeof(*h) + sizeof(*p);
payload_size = stream->stride * stream->frames_per_pdu; payload_size = stream->stride * stream->frames_per_pdu;
pdu_size = hdr_size + payload_size; pdu_size = hdr_size + payload_size;
spa_zero(stream->pdu); h->type = htons(0x8100);
p->eth.type = htons(0x8100); h->prio_cfi_id = htons((stream->prio << 13) | stream->vlan_id);
p->vlan = htonl(0x600222f0); h->etype = htons(0x22f0);
if (stream->direction == SPA_DIRECTION_OUTPUT) { if (stream->direction == SPA_DIRECTION_OUTPUT) {
p->subtype = AVB_SUBTYPE_61883_IIDC; p->subtype = AVB_SUBTYPE_61883_IIDC;
@ -272,6 +278,9 @@ struct stream *server_create_stream(struct server *server,
stream->desc = desc; stream->desc = desc;
spa_list_append(&server->streams, &stream->link); spa_list_append(&server->streams, &stream->link);
stream->prio = AVB_MSRP_PRIORITY_DEFAULT;
stream->vlan_id = AVB_DEFAULT_VLAN;
stream->id = (uint64_t)server->mac_addr[0] << 56 | stream->id = (uint64_t)server->mac_addr[0] << 56 |
(uint64_t)server->mac_addr[1] << 48 | (uint64_t)server->mac_addr[1] << 48 |
(uint64_t)server->mac_addr[2] << 40 | (uint64_t)server->mac_addr[2] << 40 |
@ -284,16 +293,16 @@ struct stream *server_create_stream(struct server *server,
AVB_MSRP_ATTRIBUTE_TYPE_LISTENER); AVB_MSRP_ATTRIBUTE_TYPE_LISTENER);
stream->talker_attr = avb_msrp_attribute_new(server->msrp, stream->talker_attr = avb_msrp_attribute_new(server->msrp,
AVB_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE); AVB_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE);
stream->talker_attr->attr.talker.vlan_id = htons(2); stream->talker_attr->attr.talker.vlan_id = htons(stream->vlan_id);
stream->talker_attr->attr.talker.tspec_max_interval_frames = stream->talker_attr->attr.talker.tspec_max_interval_frames =
htons(AVB_MSRP_TSPEC_MAX_INTERVAL_FRAMES_DEFAULT); htons(AVB_MSRP_TSPEC_MAX_INTERVAL_FRAMES_DEFAULT);
stream->talker_attr->attr.talker.priority = AVB_MSRP_PRIORITY_DEFAULT; stream->talker_attr->attr.talker.priority = stream->prio;
stream->talker_attr->attr.talker.rank = AVB_MSRP_RANK_DEFAULT; stream->talker_attr->attr.talker.rank = AVB_MSRP_RANK_DEFAULT;
stream->talker_attr->attr.talker.accumulated_latency = 0; stream->talker_attr->attr.talker.accumulated_latency = 0;
stream->vlan_attr = avb_mvrp_attribute_new(server->mvrp, stream->vlan_attr = avb_mvrp_attribute_new(server->mvrp,
AVB_MVRP_ATTRIBUTE_TYPE_VID); AVB_MVRP_ATTRIBUTE_TYPE_VID);
stream->vlan_attr->attr.vid.vlan = htons(2); stream->vlan_attr->attr.vid.vlan = htons(stream->vlan_id);
stream->buffer_data = calloc(1, BUFFER_SIZE); stream->buffer_data = calloc(1, BUFFER_SIZE);
stream->buffer_size = BUFFER_SIZE; stream->buffer_size = BUFFER_SIZE;
@ -455,14 +464,13 @@ static void handle_iec61883_packet(struct stream *stream,
{ {
uint32_t index, n_bytes; uint32_t index, n_bytes;
int32_t filled; int32_t filled;
bool overrun = false;
filled = spa_ringbuffer_get_write_index(&stream->ring, &index); filled = spa_ringbuffer_get_write_index(&stream->ring, &index);
overrun = filled > (int32_t) stream->buffer_size;
if (overrun) {
pw_log_warn("capture overrun %zd < %d", stream->buffer_size, filled);
} else {
n_bytes = ntohs(p->data_len) - 8; n_bytes = ntohs(p->data_len) - 8;
if (filled + n_bytes > stream->buffer_size) {
pw_log_debug("capture overrun");
} else {
spa_ringbuffer_write_data(&stream->ring, spa_ringbuffer_write_data(&stream->ring,
stream->buffer_data, stream->buffer_data,
stream->buffer_size, stream->buffer_size,
@ -471,7 +479,6 @@ static void handle_iec61883_packet(struct stream *stream,
index += n_bytes; index += n_bytes;
spa_ringbuffer_write_update(&stream->ring, index); spa_ringbuffer_write_update(&stream->ring, index);
} }
} }
static void on_socket_data(void *data, int fd, uint32_t mask) static void on_socket_data(void *data, int fd, uint32_t mask)
@ -491,13 +498,14 @@ static void on_socket_data(void *data, int fd, uint32_t mask)
pw_log_warn("short packet received (%d < %d)", len, pw_log_warn("short packet received (%d < %d)", len,
(int)sizeof(struct avb_packet_header)); (int)sizeof(struct avb_packet_header));
} else { } else {
struct avb_packet_iec61883 *h = (struct avb_packet_iec61883*)buffer; struct avb_frame_header *h = (void*)buffer;
struct avb_packet_iec61883 *p = SPA_PTROFF(h, sizeof(*h), void);
if (memcmp(h->eth.dest, stream->addr, 6) != 0 || if (memcmp(h->dest, stream->addr, 6) != 0 ||
h->subtype != AVB_SUBTYPE_61883_IIDC) p->subtype != AVB_SUBTYPE_61883_IIDC)
return; return;
handle_iec61883_packet(stream, h, len); handle_iec61883_packet(stream, p, len - sizeof(*h));
} }
} }
} }
@ -505,7 +513,7 @@ static void on_socket_data(void *data, int fd, uint32_t mask)
int stream_activate(struct stream *stream, uint64_t now) int stream_activate(struct stream *stream, uint64_t now)
{ {
struct server *server = stream->server; struct server *server = stream->server;
struct avb_ethernet_header *h = (struct avb_ethernet_header *)stream->pdu; struct avb_frame_header *h = (void*)stream->pdu;
int fd, res; int fd, res;
if (stream->source == NULL) { if (stream->source == NULL) {

View file

@ -55,6 +55,7 @@ struct stream {
uint8_t addr[6]; uint8_t addr[6];
struct spa_source *source; struct spa_source *source;
int prio; int prio;
int vlan_id;
int mtt; int mtt;
int t_uncertainty; int t_uncertainty;
uint32_t frames_per_pdu; uint32_t frames_per_pdu;