162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * An extensible bitmap is a bitmap that supports an 462306a36Sopenharmony_ci * arbitrary number of bits. Extensible bitmaps are 562306a36Sopenharmony_ci * used to represent sets of values, such as types, 662306a36Sopenharmony_ci * roles, categories, and classes. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Each extensible bitmap is implemented as a linked 962306a36Sopenharmony_ci * list of bitmap nodes, where each bitmap node has 1062306a36Sopenharmony_ci * an explicitly specified starting bit position within 1162306a36Sopenharmony_ci * the total bitmap. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Author : Stephen Smalley, <stephen.smalley.work@gmail.com> 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_ci#ifndef _SS_EBITMAP_H_ 1662306a36Sopenharmony_ci#define _SS_EBITMAP_H_ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <net/netlabel.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#ifdef CONFIG_64BIT 2162306a36Sopenharmony_ci#define EBITMAP_NODE_SIZE 64 2262306a36Sopenharmony_ci#else 2362306a36Sopenharmony_ci#define EBITMAP_NODE_SIZE 32 2462306a36Sopenharmony_ci#endif 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define EBITMAP_UNIT_NUMS ((EBITMAP_NODE_SIZE-sizeof(void *)-sizeof(u32))\ 2762306a36Sopenharmony_ci / sizeof(unsigned long)) 2862306a36Sopenharmony_ci#define EBITMAP_UNIT_SIZE BITS_PER_LONG 2962306a36Sopenharmony_ci#define EBITMAP_SIZE (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE) 3062306a36Sopenharmony_ci#define EBITMAP_BIT 1ULL 3162306a36Sopenharmony_ci#define EBITMAP_SHIFT_UNIT_SIZE(x) \ 3262306a36Sopenharmony_ci (((x) >> EBITMAP_UNIT_SIZE / 2) >> EBITMAP_UNIT_SIZE / 2) 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistruct ebitmap_node { 3562306a36Sopenharmony_ci struct ebitmap_node *next; 3662306a36Sopenharmony_ci unsigned long maps[EBITMAP_UNIT_NUMS]; 3762306a36Sopenharmony_ci u32 startbit; 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistruct ebitmap { 4162306a36Sopenharmony_ci struct ebitmap_node *node; /* first node in the bitmap */ 4262306a36Sopenharmony_ci u32 highbit; /* highest position in the total bitmap */ 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define ebitmap_length(e) ((e)->highbit) 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic inline unsigned int ebitmap_start_positive(const struct ebitmap *e, 4862306a36Sopenharmony_ci struct ebitmap_node **n) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci unsigned int ofs; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci for (*n = e->node; *n; *n = (*n)->next) { 5362306a36Sopenharmony_ci ofs = find_first_bit((*n)->maps, EBITMAP_SIZE); 5462306a36Sopenharmony_ci if (ofs < EBITMAP_SIZE) 5562306a36Sopenharmony_ci return (*n)->startbit + ofs; 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ci return ebitmap_length(e); 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic inline void ebitmap_init(struct ebitmap *e) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci memset(e, 0, sizeof(*e)); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic inline unsigned int ebitmap_next_positive(const struct ebitmap *e, 6662306a36Sopenharmony_ci struct ebitmap_node **n, 6762306a36Sopenharmony_ci unsigned int bit) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci unsigned int ofs; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci ofs = find_next_bit((*n)->maps, EBITMAP_SIZE, bit - (*n)->startbit + 1); 7262306a36Sopenharmony_ci if (ofs < EBITMAP_SIZE) 7362306a36Sopenharmony_ci return ofs + (*n)->startbit; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci for (*n = (*n)->next; *n; *n = (*n)->next) { 7662306a36Sopenharmony_ci ofs = find_first_bit((*n)->maps, EBITMAP_SIZE); 7762306a36Sopenharmony_ci if (ofs < EBITMAP_SIZE) 7862306a36Sopenharmony_ci return ofs + (*n)->startbit; 7962306a36Sopenharmony_ci } 8062306a36Sopenharmony_ci return ebitmap_length(e); 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci#define EBITMAP_NODE_INDEX(node, bit) \ 8462306a36Sopenharmony_ci (((bit) - (node)->startbit) / EBITMAP_UNIT_SIZE) 8562306a36Sopenharmony_ci#define EBITMAP_NODE_OFFSET(node, bit) \ 8662306a36Sopenharmony_ci (((bit) - (node)->startbit) % EBITMAP_UNIT_SIZE) 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic inline int ebitmap_node_get_bit(const struct ebitmap_node *n, 8962306a36Sopenharmony_ci unsigned int bit) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci unsigned int index = EBITMAP_NODE_INDEX(n, bit); 9262306a36Sopenharmony_ci unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci BUG_ON(index >= EBITMAP_UNIT_NUMS); 9562306a36Sopenharmony_ci if ((n->maps[index] & (EBITMAP_BIT << ofs))) 9662306a36Sopenharmony_ci return 1; 9762306a36Sopenharmony_ci return 0; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic inline void ebitmap_node_set_bit(struct ebitmap_node *n, 10162306a36Sopenharmony_ci unsigned int bit) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci unsigned int index = EBITMAP_NODE_INDEX(n, bit); 10462306a36Sopenharmony_ci unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci BUG_ON(index >= EBITMAP_UNIT_NUMS); 10762306a36Sopenharmony_ci n->maps[index] |= (EBITMAP_BIT << ofs); 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic inline void ebitmap_node_clr_bit(struct ebitmap_node *n, 11162306a36Sopenharmony_ci unsigned int bit) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci unsigned int index = EBITMAP_NODE_INDEX(n, bit); 11462306a36Sopenharmony_ci unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci BUG_ON(index >= EBITMAP_UNIT_NUMS); 11762306a36Sopenharmony_ci n->maps[index] &= ~(EBITMAP_BIT << ofs); 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define ebitmap_for_each_positive_bit(e, n, bit) \ 12162306a36Sopenharmony_ci for ((bit) = ebitmap_start_positive(e, &(n)); \ 12262306a36Sopenharmony_ci (bit) < ebitmap_length(e); \ 12362306a36Sopenharmony_ci (bit) = ebitmap_next_positive(e, &(n), bit)) \ 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ciint ebitmap_cmp(const struct ebitmap *e1, const struct ebitmap *e2); 12662306a36Sopenharmony_ciint ebitmap_cpy(struct ebitmap *dst, const struct ebitmap *src); 12762306a36Sopenharmony_ciint ebitmap_and(struct ebitmap *dst, const struct ebitmap *e1, const struct ebitmap *e2); 12862306a36Sopenharmony_ciint ebitmap_contains(const struct ebitmap *e1, const struct ebitmap *e2, u32 last_e2bit); 12962306a36Sopenharmony_ciint ebitmap_get_bit(const struct ebitmap *e, unsigned long bit); 13062306a36Sopenharmony_ciint ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); 13162306a36Sopenharmony_civoid ebitmap_destroy(struct ebitmap *e); 13262306a36Sopenharmony_ciint ebitmap_read(struct ebitmap *e, void *fp); 13362306a36Sopenharmony_ciint ebitmap_write(const struct ebitmap *e, void *fp); 13462306a36Sopenharmony_ciu32 ebitmap_hash(const struct ebitmap *e, u32 hash); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci#ifdef CONFIG_NETLABEL 13762306a36Sopenharmony_ciint ebitmap_netlbl_export(struct ebitmap *ebmap, 13862306a36Sopenharmony_ci struct netlbl_lsm_catmap **catmap); 13962306a36Sopenharmony_ciint ebitmap_netlbl_import(struct ebitmap *ebmap, 14062306a36Sopenharmony_ci struct netlbl_lsm_catmap *catmap); 14162306a36Sopenharmony_ci#else 14262306a36Sopenharmony_cistatic inline int ebitmap_netlbl_export(struct ebitmap *ebmap, 14362306a36Sopenharmony_ci struct netlbl_lsm_catmap **catmap) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci return -ENOMEM; 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_cistatic inline int ebitmap_netlbl_import(struct ebitmap *ebmap, 14862306a36Sopenharmony_ci struct netlbl_lsm_catmap *catmap) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci return -ENOMEM; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci#endif 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci#endif /* _SS_EBITMAP_H_ */ 155