2 * Administrative-group library (RFC3630, RFC5305, RFC5329, RFC7308)
4 * Copyright 2022 Hiroki Shirokura, LINE Corporation
5 * Copyright 2022 Masakazu Asama
6 * Copyright 2022 6WIND S.A.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "admin_group.h"
26 char *admin_group_string(char *out
, size_t sz
, int indent
,
27 const struct admin_group
*ag
)
36 if (admin_group_explicit_zero(ag
)) {
37 snprintf(out
, sz
, "0x00000000");
41 if (admin_group_zero(ag
)) {
42 snprintf(out
, sz
, "not-set");
46 snprintf(out
, sz
, "0x");
47 for (ssize_t i
= ag
->bitmap
.m
- 1; i
>= 0; i
--) {
50 if (ag
->bitmap
.data
[i
] == 0 && !printed
)
52 if (nb_print
!= 0 && (nb_print
% 4) == 0) {
53 snprintf(&out
[index
], sz
- index
, "\n%*s", indent
, "");
55 snprintf(&out
[index
], sz
- index
, "0x%08x ",
59 snprintf(&out
[index
], sz
- index
, "%08x ",
68 char *admin_group_standard_print(char *out
, int indent
, uint32_t bitmap
)
72 size_t ret
, line_sz
= 0, line_max_sz
;
77 snprintf(out
, ADMIN_GROUP_PRINT_MAX_SIZE
, "not-set");
81 line_max_sz
= strlen("0xffffffff ffffffff ffffffff ffffffff");
83 for (i
= 0; i
< 32; i
++) {
84 bit
= bitmap
>> i
& 1;
88 ret
= snprintf(&out
[strlen(out
)],
89 ADMIN_GROUP_PRINT_MAX_SIZE
- strlen(out
),
93 if (line_sz
>= line_max_sz
) {
94 snprintf(&out
[strlen(out
)],
95 ADMIN_GROUP_PRINT_MAX_SIZE
- strlen(out
),
100 ret
= snprintf(&out
[strlen(out
)],
101 ADMIN_GROUP_PRINT_MAX_SIZE
- strlen(out
), "%d",
110 char *admin_group_print(char *out
, int indent
, const struct admin_group
*ag
)
114 size_t ret
, line_sz
= 0, line_max_sz
;
118 if (admin_group_size(ag
) == 0) {
119 snprintf(out
, ADMIN_GROUP_PRINT_MAX_SIZE
, "not-set");
123 line_max_sz
= strlen("0xffffffff ffffffff ffffffff ffffffff");
125 for (i
= 0; i
< (admin_group_size(ag
) * WORD_SIZE
); i
++) {
126 if (!admin_group_get(ag
, i
))
129 ret
= snprintf(&out
[strlen(out
)],
130 ADMIN_GROUP_PRINT_MAX_SIZE
- strlen(out
),
134 if (line_sz
>= line_max_sz
) {
135 snprintf(&out
[strlen(out
)],
136 ADMIN_GROUP_PRINT_MAX_SIZE
- strlen(out
),
137 "\n%*s", indent
, "");
141 ret
= snprintf(&out
[strlen(out
)],
142 ADMIN_GROUP_PRINT_MAX_SIZE
- strlen(out
), "%d",
145 if (ret
>= (ADMIN_GROUP_PRINT_MAX_SIZE
- strlen(out
))) {
155 bool admin_group_cmp(const struct admin_group
*ag1
,
156 const struct admin_group
*ag2
)
160 for (i
= 0; i
< ag1
->bitmap
.m
|| i
< ag2
->bitmap
.m
; i
++) {
161 if (i
>= ag1
->bitmap
.m
) {
162 if (ag2
->bitmap
.data
[i
] != 0)
164 } else if (i
>= ag2
->bitmap
.m
) {
165 if (ag1
->bitmap
.data
[i
] != 0)
167 } else if (memcmp(&ag1
->bitmap
.data
[i
], &ag2
->bitmap
.data
[i
],
168 sizeof(word_t
)) != 0)
175 void admin_group_copy(struct admin_group
*dst
, const struct admin_group
*src
)
177 assert(bf_is_inited(src
->bitmap
));
178 if (bf_is_inited(dst
->bitmap
))
179 bf_free(dst
->bitmap
);
180 dst
->bitmap
= bf_copy(src
->bitmap
);
183 void admin_group_init(struct admin_group
*ag
)
185 assert(!bf_is_inited(ag
->bitmap
));
186 bf_init(ag
->bitmap
, WORD_SIZE
);
189 void admin_group_term(struct admin_group
*ag
)
191 assert(bf_is_inited(ag
->bitmap
));
195 word_t
admin_group_get_offset(const struct admin_group
*ag
, size_t oct_offset
)
197 assert(bf_is_inited(ag
->bitmap
));
198 if (ag
->bitmap
.m
< oct_offset
)
200 return ag
->bitmap
.data
[oct_offset
];
203 static void admin_group_extend(struct admin_group
*ag
, size_t idx
)
207 old_m
= ag
->bitmap
.m
;
211 XREALLOC(MTYPE_BITFIELD
, ag
->bitmap
.data
, m
* sizeof(word_t
));
212 memset(&ag
->bitmap
.data
[old_m
], 0, (m
- old_m
) * sizeof(word_t
));
215 void admin_group_set(struct admin_group
*ag
, size_t pos
)
217 size_t idx
= bf_index(pos
);
219 if (idx
>= ag
->bitmap
.m
)
220 admin_group_extend(ag
, idx
);
222 ag
->bitmap
.data
[idx
] |= 1 << (bf_offset(pos
));
224 if (idx
>= ag
->bitmap
.n
)
225 ag
->bitmap
.n
= idx
+ 1;
228 void admin_group_unset(struct admin_group
*ag
, size_t pos
)
230 if (bf_index(pos
) > (ag
->bitmap
.m
- 1))
232 bf_release_index(ag
->bitmap
, pos
);
233 ag
->bitmap
.n
= admin_group_size(ag
);
236 int admin_group_get(const struct admin_group
*ag
, size_t pos
)
238 size_t admin_group_length
= admin_group_size(ag
);
242 if (admin_group_length
== 0)
247 if (idx
>= admin_group_length
)
250 oct_offset
= admin_group_get_offset(ag
, idx
);
251 return oct_offset
>> pos
& 1;
254 void admin_group_bulk_set(struct admin_group
*ag
, uint32_t bitmap
,
258 if (bitmap
== 0 && oct_offset
== 0) {
259 admin_group_allow_explicit_zero(ag
);
263 if (oct_offset
>= ag
->bitmap
.m
)
264 admin_group_extend(ag
, oct_offset
);
266 ag
->bitmap
.data
[oct_offset
] = bitmap
;
268 if (oct_offset
>= ag
->bitmap
.n
)
269 ag
->bitmap
.n
= oct_offset
+ 1;
272 size_t admin_group_size(const struct admin_group
*ag
)
276 for (size_t i
= 0; i
< ag
->bitmap
.m
; i
++)
277 if (ag
->bitmap
.data
[i
] != 0)
282 size_t admin_group_nb_words(const struct admin_group
*ag
)
287 void admin_group_clear(struct admin_group
*ag
)
289 for (size_t i
= 0; i
< ag
->bitmap
.m
; i
++)
290 ag
->bitmap
.data
[i
] = 0;
294 bool admin_group_zero(const struct admin_group
*ag
)
296 for (size_t i
= 0; i
< ag
->bitmap
.m
; i
++)
297 if (ag
->bitmap
.data
[i
] != 0)
303 bool admin_group_explicit_zero(const struct admin_group
*ag
)
305 return ag
->bitmap
.n
== 1 && ag
->bitmap
.data
[0] == 0;
308 void admin_group_allow_explicit_zero(struct admin_group
*ag
)
310 if (admin_group_zero(ag
))
314 void admin_group_disallow_explicit_zero(struct admin_group
*ag
)
316 if (admin_group_zero(ag
))
320 /* link_std_ag: admin-group in the RFC5305 section 3.1 format
321 * link_ext_ag: admin-group in the RFC7308 format
322 * RFC7308 specifies in section 2.3.1 that:
323 * "If both an AG and EAG are present, a receiving node MUST use the AG
324 * as the first 32 bits (0-31) of administrative color and use the EAG
325 * for bits 32 and higher, if present."
327 bool admin_group_match_any(const struct admin_group
*fad_ag
,
328 const uint32_t *link_std_ag
,
329 const struct admin_group
*link_ext_ag
)
331 size_t fad_ag_sz
, link_ag_sz
, i
;
332 uint32_t link_ag_bitmap
, fad_ag_bitmap
;
336 /* get the size of admin-groups: i.e. number of used words */
337 fad_ag_sz
= admin_group_size(fad_ag
);
338 if (link_std_ag
&& link_ext_ag
) {
339 link_ag_sz
= admin_group_size(link_ext_ag
);
342 } else if (link_std_ag
&& !link_ext_ag
)
344 else if (!link_std_ag
&& link_ext_ag
)
345 link_ag_sz
= admin_group_size(link_ext_ag
);
349 for (i
= 0; i
< fad_ag_sz
&& i
< link_ag_sz
; i
++) {
350 fad_ag_bitmap
= fad_ag
->bitmap
.data
[i
];
351 if (i
== 0 && link_std_ag
)
352 link_ag_bitmap
= *link_std_ag
;
354 link_ag_bitmap
= link_ext_ag
->bitmap
.data
[i
];
356 if (fad_ag_bitmap
& link_ag_bitmap
)
362 /* same comments as admin_group_match_any() */
363 bool admin_group_match_all(const struct admin_group
*fad_ag
,
364 const uint32_t *link_std_ag
,
365 const struct admin_group
*link_ext_ag
)
367 size_t fad_ag_sz
, link_ag_sz
, i
;
368 uint32_t link_ag_bitmap
, fad_ag_bitmap
;
372 /* get the size of admin-groups: i.e. number of used words */
373 fad_ag_sz
= admin_group_size(fad_ag
);
374 if (link_std_ag
&& link_ext_ag
) {
375 link_ag_sz
= admin_group_size(link_ext_ag
);
378 } else if (link_std_ag
&& !link_ext_ag
)
380 else if (!link_std_ag
&& link_ext_ag
)
381 link_ag_sz
= admin_group_size(link_ext_ag
);
385 if (fad_ag_sz
> link_ag_sz
)
388 for (i
= 0; i
< fad_ag_sz
; i
++) {
389 fad_ag_bitmap
= fad_ag
->bitmap
.data
[i
];
390 if (fad_ag_bitmap
== 0)
393 if (i
== 0 && link_std_ag
)
394 link_ag_bitmap
= *link_std_ag
;
396 link_ag_bitmap
= link_ext_ag
->bitmap
.data
[i
];
398 if ((fad_ag_bitmap
& link_ag_bitmap
) != fad_ag_bitmap
)