diff --git a/Makefile.dep b/Makefile.dep index a49f2ca0e081..ee10ee9edfd1 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -196,6 +196,10 @@ ifneq (,$(filter gnrc_netif,$(USEMODULE))) endif endif +ifneq (,$(filter gnrc_netif_bus,$(USEMODULE))) + USEMODULE += core_msg_bus +endif + ifneq (,$(filter gnrc_netif_events,$(USEMODULE))) USEMODULE += core_thread_flags USEMODULE += event diff --git a/core/include/msg_bus.h b/core/include/msg_bus.h index 6d6cb171107d..0faed44c20c1 100644 --- a/core/include/msg_bus.h +++ b/core/include/msg_bus.h @@ -103,6 +103,7 @@ static inline bool msg_is_from_bus(const msg_bus_t *bus, const msg_t *msg) * posted on the bus. * * Events can be received with @ref msg_receive. + * **The contents of the received message must not be modified.** * * @param[in] bus The message bus to attach to * @param[in] entry Message bus subscriber entry @@ -194,13 +195,13 @@ int msg_send_bus(msg_t *m, msg_bus_t *bus); * * @return The number of threads the event was posted to. */ -static inline int msg_bus_post(msg_bus_t *bus, uint8_t type, char *arg) +static inline int msg_bus_post(msg_bus_t *bus, uint8_t type, const void *arg) { assert(type < 32); msg_t m = { .type = type | ((bus->id) << 5), - .content.ptr = arg, + .content.ptr = (void *)arg, }; return msg_send_bus(&m, bus); diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index 34fc2385dfbd..e423cfde7aa5 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -31,6 +31,7 @@ PSEUDOMODULES += gnrc_netdev_default PSEUDOMODULES += gnrc_neterr PSEUDOMODULES += gnrc_netapi_callbacks PSEUDOMODULES += gnrc_netapi_mbox +PSEUDOMODULES += gnrc_netif_bus PSEUDOMODULES += gnrc_netif_events PSEUDOMODULES += gnrc_pktbuf_cmd PSEUDOMODULES += gnrc_netif_6lo diff --git a/sys/include/net/gnrc/netif.h b/sys/include/net/gnrc/netif.h index 7538caf5377d..94f122082e1b 100644 --- a/sys/include/net/gnrc/netif.h +++ b/sys/include/net/gnrc/netif.h @@ -30,6 +30,9 @@ #include "kernel_types.h" #include "msg.h" +#ifdef MODULE_GNRC_NETIF_BUS +#include "msg_bus.h" +#endif #include "event.h" #include "net/ipv6/addr.h" #include "net/gnrc/netapi.h" @@ -64,6 +67,35 @@ extern "C" { #endif +/** + * @brief Per-Interface Event Message Busses + */ +typedef enum { +#ifdef MODULE_GNRC_IPV6 + GNRC_NETIF_BUS_IPV6, /**< provides @ref gnrc_ipv6_event_t + messages to subscribers */ +#endif + GNRC_NETIF_BUS_NUMOF +} gnrc_netif_bus_t; + +/** + * @brief Event types for GNRC_NETIF_BUS_IPV6 per-interface message bus + */ +typedef enum { + /** + * @brief Address becomes valid + * + * The event is generated when an address on the interface becomes valid. + * The message payload contains a pointer to the respective + * @ref ipv6_addr_t struct. + * + * @note If the address on the interface changed between sending + * the event and processing it, the pointer will point to the new address + * which might *not* be valid. + */ + GNRC_IPV6_EVENT_ADDR_VALID, +} gnrc_ipv6_event_t; + /** * @brief Operations to an interface */ @@ -87,8 +119,11 @@ typedef struct { gnrc_netif_ipv6_t ipv6; /**< IPv6 component */ #endif #if IS_USED(MODULE_GNRC_NETIF_MAC) || defined(DOXYGEN) - gnrc_netif_mac_t mac; /**< @ref net_gnrc_mac component */ + gnrc_netif_mac_t mac; /**< @ref net_gnrc_mac component */ #endif /* IS_USED(MODULE_GNRC_NETIF_MAC) || defined(DOXYGEN) */ +#if IS_USED(MODULE_GNRC_NETIF_BUS) || DOXYGEN + msg_bus_t bus[GNRC_NETIF_BUS_NUMOF]; /**< Event Message Bus */ +#endif /** * @brief Flags for the interface * @@ -566,6 +601,23 @@ static inline int gnrc_netif_send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt) return gnrc_netapi_send(netif->pid, pkt); } +#if defined(MODULE_GNRC_NETIF_BUS) || DOXYGEN +/** + * @brief Get a message bus of a given @ref gnrc_netif_t interface. + * + * @param netif pointer to the interface + * @param type GNRC message bus [type](@ref gnrc_netif_bus_t) + * + * @return the message bus for the interface + */ +static inline msg_bus_t* gnrc_netif_get_bus(gnrc_netif_t *netif, + gnrc_netif_bus_t type) +{ + assert(type < GNRC_NETIF_BUS_NUMOF); + return &netif->bus[type]; +} +#endif /* MODULE_GNRC_NETIF_BUS */ + #ifdef __cplusplus } #endif diff --git a/sys/include/net/gnrc/netif/internal.h b/sys/include/net/gnrc/netif/internal.h index b1bed3ca8c8e..07ae858f2c3b 100644 --- a/sys/include/net/gnrc/netif/internal.h +++ b/sys/include/net/gnrc/netif/internal.h @@ -284,6 +284,25 @@ void gnrc_netif_ipv6_group_leave_internal(gnrc_netif_t *netif, */ int gnrc_netif_ipv6_group_idx(gnrc_netif_t *netif, const ipv6_addr_t *addr); + +/** + * @brief Posts a message to the IPv6 event bus of the interface + * + * @param[in] netif Pointer to the interface + * @param[in] type [Type of the event](@ref gnrc_ipv6_event_t) + * @param[in] ctx The context of the event + */ +static inline void gnrc_netif_ipv6_bus_post(gnrc_netif_t *netif, int type, + const void *ctx) +{ +#ifdef MODULE_GNRC_NETIF_BUS + msg_bus_post(&netif->bus[GNRC_NETIF_BUS_IPV6], type, ctx); +#else + (void) netif; + (void) type; + (void) ctx; +#endif +} #endif /* IS_USED(MODULE_GNRC_NETIF_IPV6) || defined(DOXYGEN) */ /** diff --git a/sys/net/gnrc/netif/gnrc_netif.c b/sys/net/gnrc/netif/gnrc_netif.c index 224a6c7a76a9..14180be44e72 100644 --- a/sys/net/gnrc/netif/gnrc_netif.c +++ b/sys/net/gnrc/netif/gnrc_netif.c @@ -67,6 +67,11 @@ int gnrc_netif_create(gnrc_netif_t *netif, char *stack, int stacksize, "more than one interface is being registered.\n"); assert(netif_iter(NULL) == NULL); } +#ifdef MODULE_GNRC_NETIF_BUS + for (int i = 0; i < GNRC_NETIF_BUS_NUMOF; ++i) { + msg_bus_init(&netif->bus[i]); + } +#endif rmutex_init(&netif->mutex); netif->ops = ops; netif_register((netif_t*) netif); @@ -660,6 +665,8 @@ int gnrc_netif_ipv6_addr_add_internal(gnrc_netif_t *netif, gnrc_ipv6_nib_pl_set(netif->pid, addr, pfx_len, UINT32_MAX, UINT32_MAX); } + + gnrc_netif_ipv6_bus_post(netif, GNRC_IPV6_EVENT_ADDR_VALID, &netif->ipv6.addrs[idx]); } #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_SLAAC) else if (!gnrc_netif_is_6ln(netif)) { diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.c index 7d7120e50b51..1cbf54d102df 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-6ln.c @@ -110,6 +110,8 @@ uint8_t _handle_aro(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6, GNRC_IPV6_NIB_REREG_ADDRESS, &netif->ipv6.addrs_timers[idx], rereg_time); + gnrc_netif_ipv6_bus_post(netif, GNRC_IPV6_EVENT_ADDR_VALID, + &netif->ipv6.addrs[idx]); break; } case SIXLOWPAN_ND_STATUS_DUP: diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c index 55a6da233cf6..3a977edba0d7 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-slaac.c @@ -78,6 +78,7 @@ void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx, * locked here) */ netif->ipv6.addrs_flags[idx] &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK; netif->ipv6.addrs_flags[idx] |= GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID; + gnrc_netif_ipv6_bus_post(netif, GNRC_IPV6_EVENT_ADDR_VALID, &netif->ipv6.addrs[idx]); } #endif /* CONFIG_GNRC_IPV6_NIB_6LN */ #if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_6LN) @@ -211,6 +212,7 @@ void _handle_valid_addr(const ipv6_addr_t *addr) if (idx >= 0) { netif->ipv6.addrs_flags[idx] &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK; netif->ipv6.addrs_flags[idx] |= GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID; + gnrc_netif_ipv6_bus_post(netif, GNRC_IPV6_EVENT_ADDR_VALID, &netif->ipv6.addrs[idx]); } if (netif != NULL) { /* was acquired in `_get_netif_state()` */