From: Vincent Bernat Date: Sat, 1 Feb 2020 18:35:56 +0000 (+0100) Subject: interfaces: move bitmaps function to a dedicated file X-Git-Tag: 1.0.5~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8b2b28f54595bc22cd1212721e9a37fbe0c83c9c;p=thirdparty%2Flldpd.git interfaces: move bitmaps function to a dedicated file Also add some simple tests. --- diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am index 2de82011..0d5f2f37 100644 --- a/src/daemon/Makefile.am +++ b/src/daemon/Makefile.am @@ -20,6 +20,7 @@ liblldpd_la_SOURCES = \ interfaces.c \ event.c lldpd.c \ pattern.c \ + bitmap.c \ probes.d trace.h \ protocols/lldp.c \ protocols/cdp.c \ diff --git a/src/daemon/bitmap.c b/src/daemon/bitmap.c new file mode 100644 index 00000000..d6e4caa3 --- /dev/null +++ b/src/daemon/bitmap.c @@ -0,0 +1,65 @@ +/* -*- mode: c; c-file-style: "openbsd" -*- */ +/* + * Copyright (c) 2020 Vincent Bernat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Helpers around bitmaps */ + +#include "lldpd.h" + +/* + * Set vlan id in the bitmap + */ +void +bitmap_set(uint32_t *bmap, uint16_t vlan_id) +{ + if (vlan_id < MAX_VLAN) + bmap[vlan_id / 32] |= (((uint32_t) 1) << (vlan_id % 32)); +} + +/* + * Checks if the bitmap is empty + */ +int +bitmap_isempty(uint32_t *bmap) +{ + int i; + + for (i = 0; i < VLAN_BITMAP_LEN; i++) { + if (bmap[i] != 0) + return 0; + } + + return 1; +} + +/* + * Calculate the number of bits set in the bitmap to get total + * number of VLANs + */ +unsigned int +bitmap_numbits(uint32_t *bmap) +{ + unsigned int num = 0; + + for (int i = 0; (i < VLAN_BITMAP_LEN); i++) { + uint32_t v = bmap[i]; + v = v - ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + num += (((v + (v >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; + } + + return num; +} diff --git a/src/daemon/interfaces.c b/src/daemon/interfaces.c index 9f74eeee..3351679a 100644 --- a/src/daemon/interfaces.c +++ b/src/daemon/interfaces.c @@ -329,7 +329,7 @@ interfaces_helper_vlan(struct lldpd *cfg, struct interfaces_device *iface; TAILQ_FOREACH(iface, interfaces, next) { - if (!(iface->type & IFACE_VLAN_T) && is_bitmap_empty(iface->vlan_bmap)) + if (!(iface->type & IFACE_VLAN_T) && bitmap_isempty(iface->vlan_bmap)) continue; /* We need to find the physical interfaces of this diff --git a/src/daemon/lldpd.h b/src/daemon/lldpd.h index d5bef420..3dad7dca 100644 --- a/src/daemon/lldpd.h +++ b/src/daemon/lldpd.h @@ -388,16 +388,19 @@ void netlink_cleanup(struct lldpd *); struct lldpd_netlink; #endif -void bitmap_set(uint32_t *bmap, uint16_t vlan_id); -int is_bitmap_empty(uint32_t *bmap); - #ifndef HOST_OS_LINUX +/* interfaces-bpf.c */ int ifbpf_phys_init(struct lldpd *, struct lldpd_hardware *); #endif /* pattern.c */ int pattern_match(char *, char *, int); +/* bitmap.c */ +void bitmap_set(uint32_t *bmap, uint16_t vlan_id); +int bitmap_isempty(uint32_t *bmap); +unsigned int bitmap_numbits(uint32_t *bmap); + struct lldpd { int g_sock; struct event_base *g_base; diff --git a/src/daemon/netlink.c b/src/daemon/netlink.c index 02cb5926..f75dceb3 100644 --- a/src/daemon/netlink.c +++ b/src/daemon/netlink.c @@ -45,51 +45,6 @@ struct lldpd_netlink { struct interfaces_address_list *addresses; }; -/* - * Set vlan id in the bitmap - */ -void -bitmap_set(uint32_t *bmap, uint16_t vlan_id) -{ - if (vlan_id < MAX_VLAN) - bmap[vlan_id / 32] |= (((uint32_t) 1) << (vlan_id % 32)); -} - -/* - * Checks if the bitmap is empty - */ -int -is_bitmap_empty(uint32_t *bmap) -{ - int i; - - for (i = 0; i < VLAN_BITMAP_LEN; i++) { - if (bmap[i] != 0) - return 0; - } - - return 1; -} - -/* - * Calculate the number of bits set in the bitmap to get total - * number of VLANs - */ -static unsigned int -num_bits_set(uint32_t *bmap) -{ - unsigned int num = 0; - - for (int i = 0; (i < VLAN_BITMAP_LEN); i++) { - uint32_t v = bmap[i]; - v = v - ((v >> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >> 2) & 0x33333333); - num += (((v + (v >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; - } - - return num; -} - /** * Set netlink socket buffer size. * @@ -337,7 +292,7 @@ netlink_parse_afspec(struct interfaces_device *iff, struct rtattr *rta, int len) rta = RTA_NEXT(rta, len); } /* All enbridged interfaces will have VLAN 1 by default, ignore it */ - if (iff->vlan_bmap[0] == 2 && (num_bits_set(iff->vlan_bmap) == 1) + if (iff->vlan_bmap[0] == 2 && (bitmap_numbits(iff->vlan_bmap) == 1) && iff->pvid == 1) { log_debug("netlink", "found only default VLAN 1 on interface %s, removing", iff->name ? iff->name : "(unknown)"); @@ -541,7 +496,7 @@ netlink_merge(struct interfaces_device *old, struct interfaces_device *new) if (new->type == 0) new->type = old->type; - if (is_bitmap_empty(new->vlan_bmap) && new->type == IFACE_VLAN_T) + if (bitmap_isempty(new->vlan_bmap) && new->type == IFACE_VLAN_T) memcpy((void *)new->vlan_bmap, (void *)old->vlan_bmap, sizeof(uint32_t) * VLAN_BITMAP_LEN); diff --git a/tests/Makefile.am b/tests/Makefile.am index 49fccd2a..574f9ebf 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,7 +4,8 @@ AM_LDFLAGS = $(LLDP_LDFLAGS) $(LLDP_BIN_LDFLAGS) if HAVE_CHECK -TESTS = check_marshal check_pattern check_lldp check_cdp check_sonmp check_edp check_fixedpoint +TESTS = check_marshal check_pattern check_bitmap check_fixedpoint \ + check_lldp check_cdp check_sonmp check_edp AM_CFLAGS += @check_CFLAGS@ LDADD = $(top_builddir)/src/daemon/liblldpd.la @check_LIBS@ @libevent_LDFLAGS@ @@ -15,6 +16,9 @@ check_marshal_SOURCES = check_marshal.c \ check_pattern_SOURCES = check_pattern.c \ $(top_srcdir)/src/daemon/lldpd.h +check_bitmap_SOURCES = check_bitmap.c \ + $(top_srcdir)/src/daemon/lldpd.h + check_lldp_SOURCES = check_lldp.c \ $(top_srcdir)/src/daemon/lldpd.h \ common.h common.c check-compat.h diff --git a/tests/check_bitmap.c b/tests/check_bitmap.c new file mode 100644 index 00000000..0fe63d53 --- /dev/null +++ b/tests/check_bitmap.c @@ -0,0 +1,74 @@ +/* -*- mode: c; c-file-style: "openbsd" -*- */ +/* + * Copyright (c) 2020 Vincent Bernat + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "../src/daemon/lldpd.h" + +START_TEST(test_empty) { + uint32_t vlan_bmap[VLAN_BITMAP_LEN] = {}; + ck_assert(bitmap_isempty(vlan_bmap)); + ck_assert_int_eq(bitmap_numbits(vlan_bmap), 0); +} +END_TEST + +START_TEST(test_first_bit) { + uint32_t vlan_bmap[VLAN_BITMAP_LEN] = {}; + bitmap_set(vlan_bmap, 1); + ck_assert_int_eq(vlan_bmap[0], 2); + ck_assert_int_eq(bitmap_numbits(vlan_bmap), 1); +} +END_TEST + +START_TEST(test_some_bits) { + uint32_t vlan_bmap[VLAN_BITMAP_LEN] = {}; + bitmap_set(vlan_bmap, 1); + bitmap_set(vlan_bmap, 6); + bitmap_set(vlan_bmap, 31); + bitmap_set(vlan_bmap, 50); + ck_assert_int_eq(vlan_bmap[0], (1L << 1) | (1L << 6) | (1L << 31)); + ck_assert_int_eq(vlan_bmap[1], (1L << (50-32))); + ck_assert_int_eq(vlan_bmap[2], 0); + ck_assert_int_eq(bitmap_numbits(vlan_bmap), 4); +} +END_TEST + +Suite * +bitmap_suite(void) +{ + Suite *s = suite_create("Bitmap handling"); + + TCase *tc_bitmap = tcase_create("Bitmap handling"); + tcase_add_test(tc_bitmap, test_empty); + tcase_add_test(tc_bitmap, test_first_bit); + tcase_add_test(tc_bitmap, test_some_bits); + suite_add_tcase(s, tc_bitmap); + + return s; +} + +int +main() +{ + int number_failed; + Suite *s = bitmap_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_ENV); + number_failed = srunner_ntests_failed(sr); + srunner_free(sr); + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +}