diff --git a/sys/include/net/gnrc/netreg.h b/sys/include/net/gnrc/netreg.h index 11455c703a..cea7d13635 100644 --- a/sys/include/net/gnrc/netreg.h +++ b/sys/include/net/gnrc/netreg.h @@ -333,6 +333,19 @@ void gnrc_netreg_unregister(gnrc_nettype_t type, gnrc_netreg_entry_t *entry); */ gnrc_netreg_entry_t *gnrc_netreg_lookup(gnrc_nettype_t type, uint32_t demux_ctx); +/** + * @brief Returns number of entries with the same gnrc_netreg_entry_t::type and + * gnrc_netreg_entry_t::demux_ctx. + * + * @param[in] type Type of the protocol. + * @param[in] demux_ctx The demultiplexing context for the registered thread. + * See gnrc_netreg_entry_t::demux_ctx. + * + * @return Number of entries with the same gnrc_netreg_entry_t::type and + * gnrc_netreg_entry_t::demux_ctx as the given parameters. + */ +int gnrc_netreg_num(gnrc_nettype_t type, uint32_t demux_ctx); + /** * @brief Returns the next entry after @p entry with the same * gnrc_netreg_entry_t::type and gnrc_netreg_entry_t::demux_ctx as the diff --git a/sys/net/gnrc/netapi/gnrc_netapi.c b/sys/net/gnrc/netapi/gnrc_netapi.c index afe5998813..9d7fbee96e 100644 --- a/sys/net/gnrc/netapi/gnrc_netapi.c +++ b/sys/net/gnrc/netapi/gnrc_netapi.c @@ -94,52 +94,54 @@ static inline int _snd_rcv_mbox(mbox_t *mbox, uint16_t type, gnrc_pktsnip_t *pkt int gnrc_netapi_dispatch(gnrc_nettype_t type, uint32_t demux_ctx, uint16_t cmd, gnrc_pktsnip_t *pkt) { - int numof = 0; - gnrc_netreg_entry_t *sendto = gnrc_netreg_lookup(type, demux_ctx); + int numof = gnrc_netreg_num(type, demux_ctx); - while (sendto) { - if (numof != 0) { - gnrc_pktbuf_hold(pkt, 1); - } + if (numof != 0) { + gnrc_netreg_entry_t *sendto = gnrc_netreg_lookup(type, demux_ctx); + + gnrc_pktbuf_hold(pkt, numof - 1); + + while (sendto) { #if defined(MODULE_GNRC_NETAPI_MBOX) || defined(MODULE_GNRC_NETAPI_CALLBACKS) - int release = 0; - switch (sendto->type) { - case GNRC_NETREG_TYPE_DEFAULT: - if (_snd_rcv(sendto->target.pid, cmd, pkt) < 1) { - /* unable to dispatch packet */ - release = 1; - } - break; + int release = 0; + switch (sendto->type) { + case GNRC_NETREG_TYPE_DEFAULT: + if (_snd_rcv(sendto->target.pid, cmd, pkt) < 1) { + /* unable to dispatch packet */ + release = 1; + } + break; #ifdef MODULE_GNRC_NETAPI_MBOX - case GNRC_NETREG_TYPE_MBOX: - if (_snd_rcv_mbox(sendto->target.mbox, cmd, pkt) < 1) { - /* unable to dispatch packet */ - release = 1; - } - break; + case GNRC_NETREG_TYPE_MBOX: + if (_snd_rcv_mbox(sendto->target.mbox, cmd, pkt) < 1) { + /* unable to dispatch packet */ + release = 1; + } + break; #endif #ifdef MODULE_GNRC_NETAPI_CALLBACKS - case GNRC_NETREG_TYPE_CB: - sendto->target.cbd->cb(cmd, pkt, sendto->target.cbd->ctx); - break; + case GNRC_NETREG_TYPE_CB: + sendto->target.cbd->cb(cmd, pkt, sendto->target.cbd->ctx); + break; #endif - default: - /* unknown dispatch type */ - release = 1; - break; - } - if (release) { - gnrc_pktbuf_release(pkt); - } + default: + /* unknown dispatch type */ + release = 1; + break; + } + if (release) { + gnrc_pktbuf_release(pkt); + } #else - if (_snd_rcv(sendto->target.pid, cmd, pkt) < 1) { - /* unable to dispatch packet */ - gnrc_pktbuf_release(pkt); - } + if (_snd_rcv(sendto->target.pid, cmd, pkt) < 1) { + /* unable to dispatch packet */ + gnrc_pktbuf_release(pkt); + } #endif - numof++; - sendto = gnrc_netreg_getnext(sendto); + sendto = gnrc_netreg_getnext(sendto); + } } + return numof; } diff --git a/sys/net/gnrc/netreg/gnrc_netreg.c b/sys/net/gnrc/netreg/gnrc_netreg.c index 8d8ef83462..b77f76fbae 100644 --- a/sys/net/gnrc/netreg/gnrc_netreg.c +++ b/sys/net/gnrc/netreg/gnrc_netreg.c @@ -96,6 +96,17 @@ gnrc_netreg_entry_t *gnrc_netreg_lookup(gnrc_nettype_t type, uint32_t demux_ctx) return _netreg_lookup(NULL, type, demux_ctx); } +int gnrc_netreg_num(gnrc_nettype_t type, uint32_t demux_ctx) +{ + int num = 0; + gnrc_netreg_entry_t *entry = NULL; + + while((entry = _netreg_lookup(entry, type, demux_ctx)) != NULL) { + num++; + } + return num; +} + gnrc_netreg_entry_t *gnrc_netreg_getnext(gnrc_netreg_entry_t *entry) { return (entry ? _netreg_lookup(entry, 0, entry->demux_ctx) : NULL); diff --git a/tests/unittests/tests-netreg/tests-netreg.c b/tests/unittests/tests-netreg/tests-netreg.c index 2416dac424..b56a68861f 100644 --- a/tests/unittests/tests-netreg/tests-netreg.c +++ b/tests/unittests/tests-netreg/tests-netreg.c @@ -85,13 +85,6 @@ void test_netreg_unregister__success3(void) TEST_ASSERT_NULL(gnrc_netreg_lookup(GNRC_NETTYPE_TEST, TEST_UINT16)); } -void test_netreg_lookup__empty(void) -{ - TEST_ASSERT_NULL(gnrc_netreg_lookup(GNRC_NETTYPE_TEST, TEST_UINT16)); - TEST_ASSERT_NULL(gnrc_netreg_lookup(GNRC_NETTYPE_TEST, TEST_UINT16 + 1)); - TEST_ASSERT_NULL(gnrc_netreg_lookup(GNRC_NETTYPE_TEST, GNRC_NETREG_DEMUX_CTX_ALL)); -} - void test_netreg_lookup__wrong_type_undef(void) { TEST_ASSERT_EQUAL_INT(0, gnrc_netreg_register(GNRC_NETTYPE_TEST, &entries[0])); @@ -104,17 +97,31 @@ void test_netreg_lookup__wrong_type_numof(void) TEST_ASSERT_NULL(gnrc_netreg_lookup(GNRC_NETTYPE_NUMOF, TEST_UINT16)); } -void test_netreg_lookup__2_entries(void) +void test_netreg_num__empty(void) +{ + TEST_ASSERT_EQUAL_INT(0, gnrc_netreg_num(GNRC_NETTYPE_TEST, TEST_UINT16)); + TEST_ASSERT_EQUAL_INT(0, gnrc_netreg_num(GNRC_NETTYPE_TEST, TEST_UINT16 + 1)); + TEST_ASSERT_EQUAL_INT(0, gnrc_netreg_num(GNRC_NETTYPE_TEST, GNRC_NETREG_DEMUX_CTX_ALL)); +} + +void test_netreg_num__wrong_type_undef(void) { - gnrc_netreg_entry_t *res = NULL; - /* add first entry, first lookup != NULL; second == NULL */ TEST_ASSERT_EQUAL_INT(0, gnrc_netreg_register(GNRC_NETTYPE_TEST, &entries[0])); - TEST_ASSERT_NOT_NULL((res = gnrc_netreg_lookup(GNRC_NETTYPE_TEST, TEST_UINT16))); - TEST_ASSERT_NULL((res = gnrc_netreg_getnext(res))); - /* add second entry, both lookups != NULL */ + TEST_ASSERT_EQUAL_INT(0, gnrc_netreg_num(GNRC_NETTYPE_UNDEF, TEST_UINT16)); +} + +void test_netreg_num__wrong_type_numof(void) +{ + TEST_ASSERT_EQUAL_INT(0, gnrc_netreg_register(GNRC_NETTYPE_TEST, &entries[0])); + TEST_ASSERT_EQUAL_INT(0, gnrc_netreg_num(GNRC_NETTYPE_NUMOF, TEST_UINT16)); +} + +void test_netreg_num__2_entries(void) +{ + TEST_ASSERT_EQUAL_INT(0, gnrc_netreg_register(GNRC_NETTYPE_TEST, &entries[0])); + TEST_ASSERT_EQUAL_INT(1, gnrc_netreg_num(GNRC_NETTYPE_TEST, TEST_UINT16)); TEST_ASSERT_EQUAL_INT(0, gnrc_netreg_register(GNRC_NETTYPE_TEST, &entries[1])); - TEST_ASSERT_NOT_NULL((res = gnrc_netreg_lookup(GNRC_NETTYPE_TEST, TEST_UINT16))); - TEST_ASSERT_NOT_NULL((res = gnrc_netreg_getnext(res))); + TEST_ASSERT_EQUAL_INT(2, gnrc_netreg_num(GNRC_NETTYPE_TEST, TEST_UINT16)); } void test_netreg_getnext__NULL(void) @@ -127,7 +134,7 @@ void test_netreg_getnext__2_entries(void) { gnrc_netreg_entry_t *res = NULL; - test_netreg_lookup__2_entries(); + test_netreg_num__2_entries(); TEST_ASSERT_NOT_NULL((res = gnrc_netreg_lookup(GNRC_NETTYPE_TEST, TEST_UINT16))); TEST_ASSERT_NOT_NULL(gnrc_netreg_getnext(res)); } @@ -140,10 +147,12 @@ Test *tests_netreg_tests(void) new_TestFixture(test_netreg_unregister__success), new_TestFixture(test_netreg_unregister__success2), new_TestFixture(test_netreg_unregister__success3), - new_TestFixture(test_netreg_lookup__empty), new_TestFixture(test_netreg_lookup__wrong_type_undef), new_TestFixture(test_netreg_lookup__wrong_type_numof), - new_TestFixture(test_netreg_lookup__2_entries), + new_TestFixture(test_netreg_num__empty), + new_TestFixture(test_netreg_num__wrong_type_undef), + new_TestFixture(test_netreg_num__wrong_type_numof), + new_TestFixture(test_netreg_num__2_entries), new_TestFixture(test_netreg_getnext__NULL), new_TestFixture(test_netreg_getnext__2_entries), };