Coverage Report

Created: 2025-10-13 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openvswitch/lib/id-pool.c
Line
Count
Source
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
    ovs_assert(base <= UINT32_MAX - n_ids);
64
65
0
    pool->base = base;
66
0
    pool->n_ids = n_ids;
67
0
    pool->next_free_id = base;
68
0
    hmap_init(&pool->map);
69
0
}
70
71
static void
72
id_pool_uninit(struct id_pool *pool)
73
0
{
74
0
    struct id_node *id_node;
75
76
0
    HMAP_FOR_EACH_POP(id_node, node, &pool->map) {
77
0
        free(id_node);
78
0
    }
79
80
0
    hmap_destroy(&pool->map);
81
0
}
82
83
static struct id_node *
84
id_pool_find(struct id_pool *pool, uint32_t id)
85
0
{
86
0
    size_t hash;
87
0
    struct id_node *id_node;
88
89
0
    hash = hash_int(id, 0);
90
0
    HMAP_FOR_EACH_WITH_HASH(id_node, node, hash, &pool->map) {
91
0
        if (id == id_node->id) {
92
0
            return id_node;
93
0
        }
94
0
    }
95
0
    return NULL;
96
0
}
97
98
void
99
id_pool_add(struct id_pool *pool, uint32_t id)
100
0
{
101
0
    struct id_node *id_node = xmalloc(sizeof *id_node);
102
0
    size_t hash;
103
104
0
    id_node->id = id;
105
0
    hash = hash_int(id, 0);
106
0
    hmap_insert(&pool->map, &id_node->node, hash);
107
0
}
108
109
bool
110
id_pool_alloc_id(struct id_pool *pool, uint32_t *id_)
111
0
{
112
0
    uint32_t id;
113
114
0
    if (pool->n_ids == 0) {
115
0
        return false;
116
0
    }
117
118
0
    if (!(id_pool_find(pool, pool->next_free_id))) {
119
0
        id = pool->next_free_id;
120
0
        goto found_free_id;
121
0
    }
122
123
0
    for(id = pool->base; id < pool->base + pool->n_ids; id++) {
124
0
        if (!id_pool_find(pool, id)) {
125
0
            goto found_free_id;
126
0
        }
127
0
    }
128
129
    /* Not available. */
130
0
    return false;
131
132
0
found_free_id:
133
0
    id_pool_add(pool, id);
134
135
0
    if (id + 1 < pool->base + pool->n_ids) {
136
0
        pool->next_free_id = id + 1;
137
0
    } else {
138
0
        pool->next_free_id = pool->base;
139
0
    }
140
141
0
    *id_ = id;
142
0
    return true;
143
0
}
144
145
void
146
id_pool_free_id(struct id_pool *pool, uint32_t id)
147
0
{
148
0
    struct id_node *id_node;
149
0
    if (id >= pool->base && (id < pool->base + pool->n_ids)) {
150
0
        id_node = id_pool_find(pool, id);
151
0
        if (id_node) {
152
0
            hmap_remove(&pool->map, &id_node->node);
153
0
            if (id < pool->next_free_id) {
154
0
                pool->next_free_id = id;
155
0
            }
156
0
            free(id_node);
157
0
        }
158
0
    }
159
0
}