module-avb: add transport abstraction for pluggable network backends

Introduce struct avb_transport_ops vtable with setup/send_packet/
make_socket/destroy callbacks. The existing raw AF_PACKET socket code
becomes the default "raw" transport. avdecc_server_new() defaults to
avb_transport_raw if no transport is set, and avdecc_server_free()
delegates cleanup through the transport ops.

This enables alternative transports (e.g. loopback for testing) without
modifying protocol handler code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Christian F.K. Schaller 2026-04-07 07:05:37 -04:00 committed by Wim Taymans
parent d9821d09c7
commit a73988d38d
2 changed files with 52 additions and 9 deletions

View file

@ -84,7 +84,7 @@ static void on_socket_data(void *data, int fd, uint32_t mask)
} }
} }
int avb_server_send_packet(struct server *server, const uint8_t dest[6], static int raw_send_packet(struct server *server, const uint8_t dest[6],
uint16_t type, void *data, size_t size) uint16_t type, void *data, size_t size)
{ {
struct avb_ethernet_header *hdr = (struct avb_ethernet_header*)data; struct avb_ethernet_header *hdr = (struct avb_ethernet_header*)data;
@ -101,6 +101,12 @@ int avb_server_send_packet(struct server *server, const uint8_t dest[6],
return res; return res;
} }
int avb_server_send_packet(struct server *server, const uint8_t dest[6],
uint16_t type, void *data, size_t size)
{
return server->transport->send_packet(server, dest, type, data, size);
}
static int load_filter(int fd, uint16_t eth, const uint8_t dest[6], const uint8_t mac[6]) static int load_filter(int fd, uint16_t eth, const uint8_t dest[6], const uint8_t mac[6])
{ {
struct sock_fprog filter; struct sock_fprog filter;
@ -136,7 +142,7 @@ static int load_filter(int fd, uint16_t eth, const uint8_t dest[6], const uint8_
return 0; return 0;
} }
int avb_server_make_socket(struct server *server, uint16_t type, const uint8_t mac[6]) static int raw_make_socket(struct server *server, uint16_t type, const uint8_t mac[6])
{ {
int fd, res; int fd, res;
struct ifreq req; struct ifreq req;
@ -209,13 +215,20 @@ error_close:
return res; return res;
} }
static int setup_socket(struct server *server) int avb_server_make_socket(struct server *server, uint16_t type, const uint8_t mac[6])
{
if (server->transport && server->transport->make_socket)
return server->transport->make_socket(server, type, mac);
return raw_make_socket(server, type, mac);
}
static int raw_transport_setup(struct server *server)
{ {
struct impl *impl = server->impl; struct impl *impl = server->impl;
int fd, res; int fd, res;
static const uint8_t bmac[6] = AVB_BROADCAST_MAC; static const uint8_t bmac[6] = AVB_BROADCAST_MAC;
fd = avb_server_make_socket(server, AVB_TSN_ETH, bmac); fd = raw_make_socket(server, AVB_TSN_ETH, bmac);
if (fd < 0) if (fd < 0)
return fd; return fd;
@ -244,6 +257,21 @@ error_no_source:
return res; return res;
} }
static void raw_transport_destroy(struct server *server)
{
struct impl *impl = server->impl;
if (server->source)
pw_loop_destroy_source(impl->loop, server->source);
server->source = NULL;
}
const struct avb_transport_ops avb_transport_raw = {
.setup = raw_transport_setup,
.send_packet = raw_send_packet,
.make_socket = raw_make_socket,
.destroy = raw_transport_destroy,
};
struct server *avdecc_server_new(struct impl *impl, struct spa_dict *props) struct server *avdecc_server_new(struct impl *impl, struct spa_dict *props)
{ {
struct server *server; struct server *server;
@ -269,7 +297,10 @@ struct server *avdecc_server_new(struct impl *impl, struct spa_dict *props)
server->debug_messages = false; server->debug_messages = false;
if ((res = setup_socket(server)) < 0) if (server->transport == NULL)
server->transport = &avb_transport_raw;
if ((res = server->transport->setup(server)) < 0)
goto error_free; goto error_free;
@ -315,12 +346,10 @@ void avdecc_server_add_listener(struct server *server, struct spa_hook *listener
void avdecc_server_free(struct server *server) void avdecc_server_free(struct server *server)
{ {
struct impl *impl = server->impl;
server_destroy_descriptors(server); server_destroy_descriptors(server);
spa_list_remove(&server->link); spa_list_remove(&server->link);
if (server->source) if (server->transport)
pw_loop_destroy_source(impl->loop, server->source); server->transport->destroy(server);
pw_timer_queue_cancel(&server->timer); pw_timer_queue_cancel(&server->timer);
spa_hook_list_clean(&server->listener_list); spa_hook_list_clean(&server->listener_list);
free(server->ifname); free(server->ifname);

View file

@ -17,6 +17,15 @@ struct avb_mrp;
#define AVB_TSN_ETH 0x22f0 #define AVB_TSN_ETH 0x22f0
#define AVB_BROADCAST_MAC { 0x91, 0xe0, 0xf0, 0x01, 0x00, 0x00 }; #define AVB_BROADCAST_MAC { 0x91, 0xe0, 0xf0, 0x01, 0x00, 0x00 };
struct avb_transport_ops {
int (*setup)(struct server *server);
int (*send_packet)(struct server *server, const uint8_t dest[6],
uint16_t type, void *data, size_t size);
int (*make_socket)(struct server *server, uint16_t type,
const uint8_t mac[6]);
void (*destroy)(struct server *server);
};
struct impl { struct impl {
struct pw_loop *loop; struct pw_loop *loop;
struct pw_timer_queue *timer_queue; struct pw_timer_queue *timer_queue;
@ -77,6 +86,9 @@ struct server {
uint64_t entity_id; uint64_t entity_id;
int ifindex; int ifindex;
const struct avb_transport_ops *transport;
void *transport_data;
struct spa_source *source; struct spa_source *source;
struct pw_timer timer; struct pw_timer timer;
@ -144,6 +156,8 @@ 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,
const struct server_events *events, void *data); const struct server_events *events, void *data);
extern const struct avb_transport_ops avb_transport_raw;
int avb_server_make_socket(struct server *server, uint16_t type, const uint8_t mac[6]); int avb_server_make_socket(struct server *server, uint16_t type, const uint8_t mac[6]);
int avb_server_send_packet(struct server *server, const uint8_t dest[6], int avb_server_send_packet(struct server *server, const uint8_t dest[6],