diff --git a/sys/include/net/gnrc/netreg.h b/sys/include/net/gnrc/netreg.h index 11455c703ac0ecfd11494529a682b9a2c36ff78b..cea7d13635c5356d36957bdd364eb725932d92f4 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 afe5998813ad613e5b72dd0a009a68d45cbd2fb2..9d7fbee96ee7b232fe20a900f0db8883e4d9a4cc 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 8d8ef83462185590a0d45a2b7131031e388142c1..b77f76fbae179ee00a0b708a9f222cf73932f8e5 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 2416dac42481a1e25bc28c4f72f8da33db38bb7e..b56a68861f9fc85335fe8a5bf8d73fb1d6ca62ee 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), };