Coverage Report

Created: 2025-07-11 06:12

/src/openvswitch/lib/id-pool.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2014 Nicira, Inc.
3
 * Copyright (c) 2014 Netronome.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at:
8
 *
9
 *     http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
#include <config.h>
19
#include "id-pool.h"
20
#include "openvswitch/hmap.h"
21
#include "hash.h"
22
23
struct id_node {
24
    struct hmap_node node;
25
    uint32_t id;
26
};
27
28
struct id_pool {
29
    struct hmap map;
30
    uint32_t base;         /* IDs in the range of [base, base + n_ids). */
31
    uint32_t n_ids;        /* Total number of ids in the pool. */
32
    uint32_t next_free_id; /* Possible next free id. */
33
};
34
35
static void id_pool_init(struct id_pool *pool,
36
                         uint32_t base, uint32_t n_ids);
37
static void id_pool_uninit(struct id_pool *pool);
38
static struct id_node *id_pool_find(struct id_pool *pool, uint32_t id);
39
40
struct id_pool *
41
id_pool_create(uint32_t base, uint32_t n_ids)
42
0
{
43
0
    struct id_pool *pool;
44
45
0
    pool = xmalloc(sizeof *pool);
46
0
    id_pool_init(pool, base, n_ids);
47
48
0
    return pool;
49
0
}
50
51
void
52
id_pool_destroy(struct id_pool *pool)
53
0
{
54
0
    if (pool) {
55
0
        id_pool_uninit(pool);
56
0
        free(pool);
57
0
    }
58
0
}
59
60
static void
61
id_pool_init(struct id_pool *pool, uint32_t base, uint32_t n_ids)
62
0
{
63
0
    pool->base = base;
64
0
    pool->n_ids = n_ids;
65
0
    pool->next_free_id = base;
66
0
    hmap_init(&pool->map);
67
0
}
68
69
static void
70
id_pool_uninit(struct id_pool *pool)
71
0
{
72
0
    struct id_node *id_node;
73
74
0
    HMAP_FOR_EACH_POP(id_node, node, &pool->map) {
75
0
        free(id_node);
76
0
    }
77
78
0
    hmap_destroy(&pool->map);
79
0
}
80
81
static struct id_node *
82
id_pool_find(struct id_pool *pool, uint32_t id)
83
0
{
84
0
    size_t hash;
85
0
    struct id_node *id_node;
86
87
0
    hash = hash_int(id, 0);
88
0
    HMAP_FOR_EACH_WITH_HASH(id_node, node, hash, &pool->map) {
89
0
        if (id == id_node->id) {
90
0
            return id_node;
91
0
        }
92
0
    }
93
0
    return NULL;
94
0
}
95
96
void
97
id_pool_add(struct id_pool *pool, uint32_t id)
98
0
{
99
0
    struct id_node *id_node = xmalloc(sizeof *id_node);
100
0
    size_t hash;
101
102
0
    id_node->id = id;
103
0
    hash = hash_int(id, 0);
104
0
    hmap_insert(&pool->map, &id_node->node, hash);
105
0
}
106
107
bool
108
id_pool_alloc_id(struct id_pool *pool, uint32_t *id_)
109
0
{
110
0
    uint32_t id;
111
112
0
    if (pool->n_ids == 0) {
113
0
        return false;
114
0
    }
115
116
0
    if (!(id_pool_find(pool, pool->next_free_id))) {
117
0
        id = pool->next_free_id;
118
0
        goto found_free_id;
119
0
    }
120
121
0
    for(id = pool->base; id < pool->base + pool->n_ids; id++) {
122
0
        if (!id_pool_find(pool, id)) {
123
0
            goto found_free_id;
124
0
        }
125
0
    }
126
127
    /* Not available. */
128
0
    return false;
129
130
0
found_free_id:
131
0
    id_pool_add(pool, id);
132
133
0
    if (id + 1 < pool->base + pool->n_ids) {
134
0
        pool->next_free_id = id + 1;
135
0
    } else {
136
0
        pool->next_free_id = pool->base;
137
0
    }
138
139
0
    *id_ = id;
140
0
    return true;
141
0
}
142
143
void
144
id_pool_free_id(struct id_pool *pool, uint32_t id)
145
0
{
146
0
    struct id_node *id_node;
147
0
    if (id >= pool->base && (id < pool->base + pool->n_ids)) {
148
0
        id_node = id_pool_find(pool, id);
149
0
        if (id_node) {
150
0
            hmap_remove(&pool->map, &id_node->node);
151
0
            if (id < pool->next_free_id) {
152
0
                pool->next_free_id = id;
153
0
            }
154
0
            free(id_node);
155
0
        }
156
0
    }
157
0
}