From 9bfb23f3f8464407b4736afc014d82c07140985a Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 7 Apr 2022 15:14:45 +0200 Subject: [PATCH] avb: don't include ethernet header in in packets Move vlan_id and prio to the stream. --- src/daemon/pipewire-avb.conf.in | 14 +--- src/modules/module-avb/aaf.h | 1 - src/modules/module-avb/acmp.c | 108 +++++++++++++++++------------- src/modules/module-avb/adp.c | 83 ++++++++++++++--------- src/modules/module-avb/aecp-aem.c | 41 ++++++------ src/modules/module-avb/aecp.c | 23 ++++--- src/modules/module-avb/avb.c | 2 +- src/modules/module-avb/avdecc.c | 10 +-- src/modules/module-avb/iec61883.h | 2 - src/modules/module-avb/internal.h | 2 +- src/modules/module-avb/maap.c | 36 +++++----- src/modules/module-avb/msrp.c | 6 +- src/modules/module-avb/msrp.h | 3 + src/modules/module-avb/packets.h | 9 ++- src/modules/module-avb/stream.c | 50 ++++++++------ src/modules/module-avb/stream.h | 1 + 16 files changed, 217 insertions(+), 174 deletions(-) diff --git a/src/daemon/pipewire-avb.conf.in b/src/daemon/pipewire-avb.conf.in index d626ed9a8..b4e465f07 100644 --- a/src/daemon/pipewire-avb.conf.in +++ b/src/daemon/pipewire-avb.conf.in @@ -65,20 +65,8 @@ stream.properties = { avb.properties = { # the addresses this server listens on + #ifname = "eth0.2" 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. vm.overrides = { } diff --git a/src/modules/module-avb/aaf.h b/src/modules/module-avb/aaf.h index 6fa5acb8f..cb4871ca6 100644 --- a/src/modules/module-avb/aaf.h +++ b/src/modules/module-avb/aaf.h @@ -26,7 +26,6 @@ #define AVB_AAF_H struct avb_packet_aaf { - struct avb_ethernet_header hdr; uint8_t subtype; #if __BYTE_ORDER == __BIG_ENDIAN unsigned sv:1; diff --git a/src/modules/module-avb/acmp.c b/src/modules/module-avb/acmp.c index 7d12d3b60..18ea1ba92 100644 --- a/src/modules/module-avb/acmp.c +++ b/src/modules/module-avb/acmp.c @@ -57,21 +57,25 @@ struct acmp { }; 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 avb_ethernet_header *h; struct avb_packet_acmp *pm; + p = calloc(1, sizeof(*p) + size); if (p == NULL) return NULL; p->last_time = now; p->timeout = timeout_ms * SPA_NSEC_PER_MSEC; - p->old_sequence_id = ntohs(m->sequence_id); p->sequence_id = acmp->sequence_id[type]++; p->size = size; p->ptr = SPA_PTROFF(p, sizeof(*p), void); 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); 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; 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_STATUS(reply, AVB_ACMP_STATUS_NOT_SUPPORTED); - return avb_server_send_packet(server, reply->hdr.eth.src, - AVB_TSN_ETH, reply, len); + return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, len); } static int retry_pending(struct acmp *acmp, uint64_t now, struct pending *p) { struct server *server = acmp->server; - struct avb_packet_acmp *cmd = p->ptr; + struct avb_ethernet_header *h = p->ptr; p->retry++; p->last_time = now; - return avb_server_send_packet(server, cmd->hdr.eth.dest, - AVB_TSN_ETH, cmd, p->size); + return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, p->ptr, p->size); } static int handle_connect_tx_command(struct acmp *acmp, uint64_t now, const void *m, int len) { struct server *server = acmp->server; uint8_t buf[len]; - const struct avb_packet_acmp *p = m; - 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); + const struct avb_packet_acmp *p = SPA_PTROFF(m, sizeof(*h), void); int status = AVB_ACMP_STATUS_SUCCESS; struct stream *stream; if (be64toh(p->talker_guid) != server->entity_id) return 0; - memcpy(reply, m, len); + memcpy(buf, m, len); stream = server_find_stream(server, SPA_DIRECTION_OUTPUT, reply->talker_unique_id); 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); reply->connection_count = htons(1); - reply->stream_vlan_id = htons(2); + reply->stream_vlan_id = htons(stream->vlan_id); done: AVB_PACKET_ACMP_SET_STATUS(reply, status); - return avb_server_send_packet(server, reply->hdr.eth.dest, - AVB_TSN_ETH, reply, len); + return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, buf, len); } static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const void *m, int len) { 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 pending *pending; 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) return 0; - reply = pending->ptr; - memcpy(reply, resp, SPA_MIN((int)pending->size, len)); + h = pending->ptr; + 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); AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE); stream = server_find_stream(server, SPA_DIRECTION_INPUT, - reply->listener_unique_id); + ntohs(reply->listener_unique_id)); if (stream == NULL) 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); stream_activate(stream, now); - res = avb_server_send_packet(server, reply->hdr.eth.dest, - AVB_TSN_ETH, reply, pending->size); + res = avb_server_send_packet(server, h->dest, AVB_TSN_ETH, h, pending->size); 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; uint8_t buf[len]; - const struct avb_packet_acmp *p = m; - 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); + const struct avb_packet_acmp *p = SPA_PTROFF(m, sizeof(*h), void); int status = AVB_ACMP_STATUS_SUCCESS; struct stream *stream; if (be64toh(p->talker_guid) != server->entity_id) return 0; - memcpy(reply, m, len); + memcpy(buf, m, len); stream = server_find_stream(server, SPA_DIRECTION_OUTPUT, reply->talker_unique_id); if (stream == NULL) { @@ -225,15 +232,15 @@ static int handle_disconnect_tx_command(struct acmp *acmp, uint64_t now, const v done: AVB_PACKET_ACMP_SET_STATUS(reply, status); - return avb_server_send_packet(server, reply->hdr.eth.dest, - AVB_TSN_ETH, reply, len); + return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, buf, len); } static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const void *m, int len) { struct server *server = acmp->server; - const struct avb_packet_acmp *resp = m; + struct avb_ethernet_header *h; struct avb_packet_acmp *reply; + const struct avb_packet_acmp *resp = SPA_PTROFF(m, sizeof(*h), void); struct pending *pending; uint16_t sequence_id; struct stream *stream; @@ -248,8 +255,11 @@ static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const if (pending == NULL) return 0; - reply = pending->ptr; - memcpy(reply, resp, SPA_MIN((int)pending->size, len)); + h = pending->ptr; + 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); 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); - res = avb_server_send_packet(server, reply->hdr.eth.dest, - AVB_TSN_ETH, reply, pending->size); + res = avb_server_send_packet(server, h->dest, AVB_TSN_ETH, h, pending->size); 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) { 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; if (be64toh(p->listener_guid) != server->entity_id) 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); - if (cmd == NULL) + if (h == NULL) 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_STATUS(cmd, AVB_ACMP_STATUS_SUCCESS); - return avb_server_send_packet(server, cmd->hdr.eth.dest, - AVB_TSN_ETH, cmd, len); + return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, h, 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) { 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; if (be64toh(p->listener_guid) != server->entity_id) 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); - if (cmd == NULL) + if (h == NULL) 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_STATUS(cmd, AVB_ACMP_STATUS_SUCCESS); - return avb_server_send_packet(server, cmd->hdr.eth.dest, - AVB_TSN_ETH, cmd, len); + return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, h, len); } 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 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; int message_type; - if (ntohs(p->hdr.eth.type) != AVB_TSN_ETH) + if (ntohs(h->type) != AVB_TSN_ETH) return 0; - if (memcmp(p->hdr.eth.dest, mac, 6) != 0 && - memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0) + if (memcmp(h->dest, mac, 6) != 0 && + memcmp(h->dest, server->mac_addr, 6) != 0) return 0; 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); 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) diff --git a/src/modules/module-avb/adp.c b/src/modules/module-avb/adp.c index c8d51986f..6b13c41b7 100644 --- a/src/modules/module-avb/adp.c +++ b/src/modules/module-avb/adp.c @@ -35,9 +35,12 @@ static const uint8_t mac[6] = AVB_BROADCAST_MAC; struct entity { struct spa_list link; - struct avb_packet_adp packet; + uint64_t entity_id; uint64_t last_time; + int valid_time; unsigned advertise:1; + size_t len; + uint8_t buf[128]; }; struct adp { @@ -52,7 +55,7 @@ static struct entity *find_entity_by_id(struct adp *adp, uint64_t id) { struct entity *e; spa_list_for_each(e, &adp->entities, link) - if (be64toh(e->packet.entity_id) == id) + if (e->entity_id == id) return e; 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) { - AVB_PACKET_ADP_SET_MESSAGE_TYPE(&e->packet, AVB_ADP_MESSAGE_TYPE_ENTITY_DEPARTING); - e->packet.available_index = htonl(adp->available_index++); - avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, &e->packet, sizeof(e->packet)); + struct avb_ethernet_header *h = (void*)e->buf; + struct avb_packet_adp *p = SPA_PTROFF(h, sizeof(*h), void); + + 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; return 0; } 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); - e->packet.available_index = htonl(adp->available_index++); - avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, &e->packet, sizeof(e->packet)); + struct avb_ethernet_header *h = (void*)e->buf; + struct avb_packet_adp *p = SPA_PTROFF(h, sizeof(*h), void); + + 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; return 0; } static int send_discover(struct adp *adp, uint64_t entity_id) { - struct avb_packet_adp p; - spa_zero(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, &p, sizeof(p)); + uint8_t buf[128]; + struct avb_ethernet_header *h = (void*)buf; + struct avb_packet_adp *p = SPA_PTROFF(h, sizeof(*h), void); + size_t len = sizeof(*h) + sizeof(*p); + + spa_memzero(buf, sizeof(buf)); + 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; } @@ -96,16 +109,17 @@ static int adp_message(void *data, uint64_t now, const void *message, int len) { struct adp *adp = data; 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; int message_type; char buf[128]; uint64_t entity_id; - if (ntohs(p->hdr.eth.type) != AVB_TSN_ETH) + if (ntohs(h->type) != AVB_TSN_ETH) return 0; - if (memcmp(p->hdr.eth.dest, mac, 6) != 0 && - memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0) + if (memcmp(h->dest, mac, 6) != 0 && + memcmp(h->dest, server->mac_addr, 6) != 0) return 0; 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) 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); pw_log_info("entity %s available", 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) if (e->advertise) send_advertise(adp, now, e); - } else if (e != NULL && e->advertise && - be64toh(e->packet.entity_id) == entity_id) { + } else if (e != NULL && + e->advertise && e->entity_id == entity_id) { send_advertise(adp, now, e); } break; @@ -169,14 +186,11 @@ static void check_timeout(struct adp *adp, uint64_t now) char buf[128]; 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 + (valid_time + 2) * SPA_NSEC_PER_SEC > now) + if (e->last_time + (e->valid_time + 2) * SPA_NSEC_PER_SEC > now) continue; pw_log_info("entity %s timeout", - avb_utils_format_id(buf, sizeof(buf), - be64toh(e->packet.entity_id))); + avb_utils_format_id(buf, sizeof(buf), e->entity_id)); if (e->advertise) 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) { - int valid_time = AVB_PACKET_ADP_GET_VALID_TIME(&e->packet); char buf[128]; if (!e->advertise) 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; pw_log_debug("entity %s readvertise", - avb_utils_format_id(buf, sizeof(buf), - be64toh(e->packet.entity_id))); + avb_utils_format_id(buf, sizeof(buf), e->entity_id)); 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 entity *e; uint64_t entity_id; + struct avb_ethernet_header *h; struct avb_packet_adp *p; char buf[128]; @@ -237,13 +250,17 @@ static int check_advertise(struct adp *adp, uint64_t now) return -errno; e->advertise = true; + e->valid_time = 10; 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_SUBTYPE(&p->hdr, AVB_SUBTYPE_ADP); 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_model_id = entity->entity_model_id; diff --git a/src/modules/module-avb/aecp-aem.c b/src/modules/module-avb/aecp-aem.c index 6900648f7..22a2ac2dd 100644 --- a/src/modules/module-avb/aecp-aem.c +++ b/src/modules/module-avb/aecp-aem.c @@ -29,14 +29,14 @@ static int reply_status(struct aecp *aecp, int status, const void *m, int len) { struct server *server = aecp->server; 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_STATUS(reply, status); - return avb_server_send_packet(server, reply->hdr.eth.src, - AVB_TSN_ETH, reply, len); + return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, 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) { 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; const struct avb_packet_aecp_aem_read_descriptor *rd; 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); 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); - size = sizeof(*reply) + psize; + size = sizeof(*h) + sizeof(*reply) + psize; memcpy(buf + size, desc->ptr, desc->size); size += 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_STATUS(&reply->aecp, AVB_AECP_AEM_STATUS_SUCCESS); AVB_PACKET_SET_LENGTH(&reply->aecp.hdr, psize + 12); - return avb_server_send_packet(server, reply->aecp.hdr.eth.src, - AVB_TSN_ETH, reply, size); + return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, size); } /* GET_AVB_INFO */ static int handle_get_avb_info(struct aecp *aecp, const void *m, int len) { 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_get_avb_info *i; 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); 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) return reply_not_implemented(aecp, m, len); avb_interface = desc->ptr; - memcpy(buf, p, len); + memcpy(buf, m, len); 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_STATUS(&reply->aecp, AVB_AECP_AEM_STATUS_SUCCESS); 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->msrp_mappings_count = htons(0); - return avb_server_send_packet(server, reply->aecp.hdr.eth.src, - AVB_TSN_ETH, reply, size); + return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, size); } /* 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) { - 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; const struct cmd_info *info; diff --git a/src/modules/module-avb/aecp.c b/src/modules/module-avb/aecp.c index 1adaeddbc..3c25b0ea3 100644 --- a/src/modules/module-avb/aecp.c +++ b/src/modules/module-avb/aecp.c @@ -43,13 +43,13 @@ static int reply_not_implemented(struct aecp *aecp, const void *p, int len) { struct server *server = aecp->server; 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); - return avb_server_send_packet(server, reply->hdr.eth.src, - AVB_TSN_ETH, reply, len); + return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, len); } 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 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; int message_type; - if (ntohs(p->hdr.eth.type) != AVB_TSN_ETH) + if (ntohs(h->type) != AVB_TSN_ETH) return 0; - if (memcmp(p->hdr.eth.dest, mac, 6) != 0 && - memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0) + if (memcmp(h->dest, mac, 6) != 0 && + memcmp(h->dest, server->mac_addr, 6) != 0) return 0; if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_AECP) 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); 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); 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) diff --git a/src/modules/module-avb/avb.c b/src/modules/module-avb/avb.c index 8b589c87a..34526936f 100644 --- a/src/modules/module-avb/avb.c +++ b/src/modules/module-avb/avb.c @@ -79,7 +79,7 @@ struct pw_avb *pw_avb_new(struct pw_context *context, 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; diff --git a/src/modules/module-avb/avdecc.c b/src/modules/module-avb/avdecc.c index 1327f385b..b7d50a2b6 100644 --- a/src/modules/module-avb/avdecc.c +++ b/src/modules/module-avb/avdecc.c @@ -257,7 +257,7 @@ error_no_source: 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; int res = 0; @@ -268,7 +268,7 @@ struct server *avdecc_server_new(struct impl *impl, const char *ifname, struct s server->impl = impl; 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_list_init(&server->descriptors); 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, AVB_MSRP_ATTRIBUTE_TYPE_DOMAIN); - server->domain_attr->attr.domain.sr_class_id = 6; - server->domain_attr->attr.domain.sr_class_priority = 3; - server->domain_attr->attr.domain.sr_class_vid = htons(2); + server->domain_attr->attr.domain.sr_class_id = AVB_MSRP_CLASS_ID_DEFAULT; + server->domain_attr->attr.domain.sr_class_priority = AVB_MSRP_PRIORITY_DEFAULT; + server->domain_attr->attr.domain.sr_class_vid = htons(AVB_DEFAULT_VLAN); avb_mrp_attribute_begin(server->domain_attr->mrp, 0); avb_mrp_attribute_join(server->domain_attr->mrp, 0, true); diff --git a/src/modules/module-avb/iec61883.h b/src/modules/module-avb/iec61883.h index be438be88..d3b3a7daa 100644 --- a/src/modules/module-avb/iec61883.h +++ b/src/modules/module-avb/iec61883.h @@ -28,8 +28,6 @@ #include "packets.h" struct avb_packet_iec61883 { - struct avb_ethernet_header eth; - uint32_t vlan; uint8_t subtype; #if __BYTE_ORDER == __BIG_ENDIAN unsigned sv:1; diff --git a/src/modules/module-avb/internal.h b/src/modules/module-avb/internal.h index 6bd106024..f0a1c1499 100644 --- a/src/modules/module-avb/internal.h +++ b/src/modules/module-avb/internal.h @@ -143,7 +143,7 @@ static inline struct stream *server_find_stream(struct server *server, 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_add_listener(struct server *server, struct spa_hook *listener, diff --git a/src/modules/module-avb/maap.c b/src/modules/module-avb/maap.c index 869d552b3..b8bf0ebee 100644 --- a/src/modules/module-avb/maap.c +++ b/src/modules/module-avb/maap.c @@ -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, 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; int res = 0; uint8_t start[6]; - spa_zero(p); - memcpy(p.hdr.eth.dest, bmac, 6); - memcpy(p.hdr.eth.src, maap->server->mac_addr, 6); - 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)); + spa_memzero(buf, sizeof(buf)); + h = (void*)buf; + p = SPA_PTROFF(h, sizeof(*h), void); - AVB_PACKET_MAAP_SET_MAAP_VERSION(&p, 1); - AVB_PACKET_MAAP_SET_MESSAGE_TYPE(&p, type); + memcpy(h->dest, bmac, 6); + 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); start[4] = maap->offset >> 8; start[5] = maap->offset; - AVB_PACKET_MAAP_SET_REQUEST_START(&p, start); - AVB_PACKET_MAAP_SET_REQUEST_COUNT(&p, maap->count); + AVB_PACKET_MAAP_SET_REQUEST_START(p, start); + AVB_PACKET_MAAP_SET_REQUEST_COUNT(p, maap->count); if (conflict_count) { - AVB_PACKET_MAAP_SET_CONFLICT_START(&p, conflict_start); - AVB_PACKET_MAAP_SET_CONFLICT_COUNT(&p, conflict_count); + AVB_PACKET_MAAP_SET_CONFLICT_START(p, conflict_start); + AVB_PACKET_MAAP_SET_CONFLICT_COUNT(p, conflict_count); } if (maap->server->debug_messages) { 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; pw_log_warn("got send error: %m"); } diff --git a/src/modules/module-avb/msrp.c b/src/modules/module-avb/msrp.c index 271043eff..85d3ff9be 100644 --- a/src/modules/module-avb/msrp.c +++ b/src/modules/module-avb/msrp.c @@ -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) { pw_log_info("domain"); - pw_log_info(" %d", d->sr_class_id); - pw_log_info(" %d", d->sr_class_priority); - pw_log_info(" %d", ntohs(d->sr_class_vid)); + pw_log_info(" id: %d", d->sr_class_id); + pw_log_info(" prio: %d", d->sr_class_priority); + 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) diff --git a/src/modules/module-avb/msrp.h b/src/modules/module-avb/msrp.h index 675392dc4..0922e6bf9 100644 --- a/src/modules/module-avb/msrp.h +++ b/src/modules/module-avb/msrp.h @@ -98,6 +98,9 @@ struct avb_packet_msrp_listener { } __attribute__ ((__packed__)); /* domain discovery */ +#define AVB_MSRP_CLASS_ID_DEFAULT 6 +#define AVB_DEFAULT_VLAN 2 + struct avb_packet_msrp_domain { uint8_t sr_class_id; uint8_t sr_class_priority; diff --git a/src/modules/module-avb/packets.h b/src/modules/module-avb/packets.h index fef147aa0..f35738a43 100644 --- a/src/modules/module-avb/packets.h +++ b/src/modules/module-avb/packets.h @@ -54,8 +54,15 @@ struct avb_ethernet_header { uint16_t type; } __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_ethernet_header eth; uint8_t subtype; #if __BYTE_ORDER == __BIG_ENDIAN unsigned sv:1; /* stream_id valid */ diff --git a/src/modules/module-avb/stream.c b/src/modules/module-avb/stream.c index 70dcf7c06..e176ff470 100644 --- a/src/modules/module-avb/stream.c +++ b/src/modules/module-avb/stream.c @@ -67,7 +67,7 @@ static void on_source_stream_process(void *data) avail = spa_ringbuffer_get_read_index(&stream->ring, &index); 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); } else { 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; int pdu_count; 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); @@ -186,16 +187,21 @@ static void on_sink_stream_process(void *data) 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; - 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; pdu_size = hdr_size + payload_size; - spa_zero(stream->pdu); - p->eth.type = htons(0x8100); - p->vlan = htonl(0x600222f0); + h->type = htons(0x8100); + h->prio_cfi_id = htons((stream->prio << 13) | stream->vlan_id); + h->etype = htons(0x22f0); if (stream->direction == SPA_DIRECTION_OUTPUT) { p->subtype = AVB_SUBTYPE_61883_IIDC; @@ -272,6 +278,9 @@ struct stream *server_create_stream(struct server *server, stream->desc = desc; 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 | (uint64_t)server->mac_addr[1] << 48 | (uint64_t)server->mac_addr[2] << 40 | @@ -284,16 +293,16 @@ struct stream *server_create_stream(struct server *server, AVB_MSRP_ATTRIBUTE_TYPE_LISTENER); stream->talker_attr = avb_msrp_attribute_new(server->msrp, 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 = 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.accumulated_latency = 0; stream->vlan_attr = avb_mvrp_attribute_new(server->mvrp, 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_size = BUFFER_SIZE; @@ -455,14 +464,13 @@ static void handle_iec61883_packet(struct stream *stream, { uint32_t index, n_bytes; int32_t filled; - bool overrun = false; 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); + n_bytes = ntohs(p->data_len) - 8; + + if (filled + n_bytes > stream->buffer_size) { + pw_log_debug("capture overrun"); } else { - n_bytes = ntohs(p->data_len) - 8; spa_ringbuffer_write_data(&stream->ring, stream->buffer_data, stream->buffer_size, @@ -471,7 +479,6 @@ static void handle_iec61883_packet(struct stream *stream, index += n_bytes; spa_ringbuffer_write_update(&stream->ring, index); } - } 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, (int)sizeof(struct avb_packet_header)); } 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 || - h->subtype != AVB_SUBTYPE_61883_IIDC) + if (memcmp(h->dest, stream->addr, 6) != 0 || + p->subtype != AVB_SUBTYPE_61883_IIDC) 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) { 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; if (stream->source == NULL) { diff --git a/src/modules/module-avb/stream.h b/src/modules/module-avb/stream.h index e09fd59ac..d3710ef1e 100644 --- a/src/modules/module-avb/stream.h +++ b/src/modules/module-avb/stream.h @@ -55,6 +55,7 @@ struct stream { uint8_t addr[6]; struct spa_source *source; int prio; + int vlan_id; int mtt; int t_uncertainty; uint32_t frames_per_pdu;