]> git.proxmox.com Git - mirror_frr.git/blame - lib/plist.c
Merge pull request #8078 from idryzhov/fix-zebra-vni
[mirror_frr.git] / lib / plist.c
CommitLineData
718e3744 1/* Prefix list functions.
2 * Copyright (C) 1999 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your
9 * option) any later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 19 */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "command.h"
25#include "memory.h"
26#include "plist.h"
27#include "sockunion.h"
28#include "buffer.h"
fbf5d033 29#include "log.h"
518f0eb1 30#include "routemap.h"
6f1ccc12 31#include "lib/json.h"
b85120bc 32#include "libfrr.h"
718e3744 33
a38401b6 34#include "plist_int.h"
718e3744 35
bf8d3d6a
DL
36DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST, "Prefix List");
37DEFINE_MTYPE_STATIC(LIB, MPREFIX_LIST_STR, "Prefix List Str");
38DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST_ENTRY, "Prefix List Entry");
39DEFINE_MTYPE_STATIC(LIB, PREFIX_LIST_TRIE, "Prefix List Trie Table");
4a1ab8e4 40
7e111b6b
DL
41/* not currently changeable, code assumes bytes further down */
42#define PLC_BITS 8
43#define PLC_LEN (1 << PLC_BITS)
44#define PLC_MAXLEVELV4 2 /* /24 for IPv4 */
45#define PLC_MAXLEVELV6 4 /* /48 for IPv6 */
46#define PLC_MAXLEVEL 4 /* max(v4,v6) */
47
48struct pltrie_entry {
49 union {
50 struct pltrie_table *next_table;
51 struct prefix_list_entry *final_chain;
52 };
53
54 struct prefix_list_entry *up_chain;
55};
56
57struct pltrie_table {
58 struct pltrie_entry entries[PLC_LEN];
59};
60
718e3744 61/* List of struct prefix_list. */
d62a17ae 62struct prefix_list_list {
63 struct prefix_list *head;
64 struct prefix_list *tail;
718e3744 65};
66
67/* Master structure of prefix_list. */
d62a17ae 68struct prefix_master {
69 /* List of prefix_list which name is number. */
70 struct prefix_list_list num;
718e3744 71
d62a17ae 72 /* List of prefix_list which name is string. */
73 struct prefix_list_list str;
718e3744 74
d62a17ae 75 /* Whether sequential number is used. */
e11d84ad 76 bool seqnum;
718e3744 77
d62a17ae 78 /* The latest update. */
79 struct prefix_list *recent;
718e3744 80
d62a17ae 81 /* Hook function which is executed when new prefix_list is added. */
82 void (*add_hook)(struct prefix_list *);
718e3744 83
d62a17ae 84 /* Hook function which is executed when prefix_list is deleted. */
85 void (*delete_hook)(struct prefix_list *);
7e111b6b 86
d62a17ae 87 /* number of bytes that have a trie level */
88 size_t trie_depth;
718e3744 89};
90
91/* Static structure of IPv4 prefix_list's master. */
d62a17ae 92static struct prefix_master prefix_master_ipv4 = {
93 {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV4,
718e3744 94};
95
718e3744 96/* Static structure of IPv6 prefix-list's master. */
d62a17ae 97static struct prefix_master prefix_master_ipv6 = {
98 {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV6,
718e3744 99};
718e3744 100
101/* Static structure of BGP ORF prefix_list's master. */
d62a17ae 102static struct prefix_master prefix_master_orf_v4 = {
103 {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV4,
c7da3d50
DL
104};
105
106/* Static structure of BGP ORF prefix_list's master. */
d62a17ae 107static struct prefix_master prefix_master_orf_v6 = {
108 {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV6,
718e3744 109};
6b0655a2 110
d62a17ae 111static struct prefix_master *prefix_master_get(afi_t afi, int orf)
718e3744 112{
d62a17ae 113 if (afi == AFI_IP)
114 return orf ? &prefix_master_orf_v4 : &prefix_master_ipv4;
115 if (afi == AFI_IP6)
116 return orf ? &prefix_master_orf_v6 : &prefix_master_ipv6;
117 return NULL;
718e3744 118}
119
d62a17ae 120const char *prefix_list_name(struct prefix_list *plist)
a38401b6 121{
d62a17ae 122 return plist->name;
a38401b6
DL
123}
124
427f8e61
DL
125afi_t prefix_list_afi(struct prefix_list *plist)
126{
127 if (plist->master == &prefix_master_ipv4
128 || plist->master == &prefix_master_orf_v4)
129 return AFI_IP;
130 return AFI_IP6;
131}
132
718e3744 133/* Lookup prefix_list from list of prefix_list by name. */
d62a17ae 134static struct prefix_list *prefix_list_lookup_do(afi_t afi, int orf,
135 const char *name)
718e3744 136{
d62a17ae 137 struct prefix_list *plist;
138 struct prefix_master *master;
718e3744 139
d62a17ae 140 if (name == NULL)
141 return NULL;
718e3744 142
d62a17ae 143 master = prefix_master_get(afi, orf);
144 if (master == NULL)
145 return NULL;
718e3744 146
d62a17ae 147 for (plist = master->num.head; plist; plist = plist->next)
148 if (strcmp(plist->name, name) == 0)
149 return plist;
718e3744 150
d62a17ae 151 for (plist = master->str.head; plist; plist = plist->next)
152 if (strcmp(plist->name, name) == 0)
153 return plist;
718e3744 154
d62a17ae 155 return NULL;
718e3744 156}
157
d62a17ae 158struct prefix_list *prefix_list_lookup(afi_t afi, const char *name)
c7da3d50 159{
d62a17ae 160 return prefix_list_lookup_do(afi, 0, name);
c7da3d50
DL
161}
162
d62a17ae 163struct prefix_list *prefix_bgp_orf_lookup(afi_t afi, const char *name)
c7da3d50 164{
d62a17ae 165 return prefix_list_lookup_do(afi, 1, name);
c7da3d50
DL
166}
167
d62a17ae 168static struct prefix_list *prefix_list_new(void)
718e3744 169{
d62a17ae 170 struct prefix_list *new;
718e3744 171
d62a17ae 172 new = XCALLOC(MTYPE_PREFIX_LIST, sizeof(struct prefix_list));
173 return new;
718e3744 174}
175
d62a17ae 176static void prefix_list_free(struct prefix_list *plist)
718e3744 177{
d62a17ae 178 XFREE(MTYPE_PREFIX_LIST, plist);
718e3744 179}
180
2fb71798 181struct prefix_list_entry *prefix_list_entry_new(void)
718e3744 182{
d62a17ae 183 struct prefix_list_entry *new;
718e3744 184
d62a17ae 185 new = XCALLOC(MTYPE_PREFIX_LIST_ENTRY,
186 sizeof(struct prefix_list_entry));
187 return new;
718e3744 188}
189
a7b28218 190void prefix_list_entry_free(struct prefix_list_entry *pentry)
718e3744 191{
d62a17ae 192 XFREE(MTYPE_PREFIX_LIST_ENTRY, pentry);
718e3744 193}
194
195/* Insert new prefix list to list of prefix_list. Each prefix_list
196 is sorted by the name. */
d62a17ae 197static struct prefix_list *prefix_list_insert(afi_t afi, int orf,
198 const char *name)
199{
200 unsigned int i;
201 long number;
202 struct prefix_list *plist;
203 struct prefix_list *point;
204 struct prefix_list_list *list;
205 struct prefix_master *master;
206
207 master = prefix_master_get(afi, orf);
208 if (master == NULL)
209 return NULL;
210
211 /* Allocate new prefix_list and copy given name. */
212 plist = prefix_list_new();
213 plist->name = XSTRDUP(MTYPE_MPREFIX_LIST_STR, name);
214 plist->master = master;
215 plist->trie =
216 XCALLOC(MTYPE_PREFIX_LIST_TRIE, sizeof(struct pltrie_table));
217
218 /* If name is made by all digit character. We treat it as
219 number. */
220 for (number = 0, i = 0; i < strlen(name); i++) {
fefa5e0f 221 if (isdigit((unsigned char)name[i]))
d62a17ae 222 number = (number * 10) + (name[i] - '0');
223 else
224 break;
225 }
98645ada 226
d62a17ae 227 /* In case of name is all digit character */
228 if (i == strlen(name)) {
229 plist->type = PREFIX_TYPE_NUMBER;
230
231 /* Set prefix_list to number list. */
232 list = &master->num;
233
234 for (point = list->head; point; point = point->next)
235 if (atol(point->name) >= number)
236 break;
237 } else {
238 plist->type = PREFIX_TYPE_STRING;
239
240 /* Set prefix_list to string list. */
241 list = &master->str;
242
243 /* Set point to insertion point. */
244 for (point = list->head; point; point = point->next)
245 if (strcmp(point->name, name) >= 0)
246 break;
247 }
248
249 /* In case of this is the first element of master. */
250 if (list->head == NULL) {
251 list->head = list->tail = plist;
252 return plist;
253 }
254
255 /* In case of insertion is made at the tail of access_list. */
256 if (point == NULL) {
257 plist->prev = list->tail;
258 list->tail->next = plist;
259 list->tail = plist;
260 return plist;
261 }
262
263 /* In case of insertion is made at the head of access_list. */
264 if (point == list->head) {
265 plist->next = list->head;
266 list->head->prev = plist;
267 list->head = plist;
268 return plist;
269 }
270
271 /* Insertion is made at middle of the access_list. */
272 plist->next = point;
273 plist->prev = point->prev;
274
275 if (point->prev)
276 point->prev->next = plist;
277 point->prev = plist;
278
279 return plist;
280}
281
2fb71798 282struct prefix_list *prefix_list_get(afi_t afi, int orf, const char *name)
718e3744 283{
d62a17ae 284 struct prefix_list *plist;
285
286 plist = prefix_list_lookup_do(afi, orf, name);
718e3744 287
d62a17ae 288 if (plist == NULL)
289 plist = prefix_list_insert(afi, orf, name);
290 return plist;
291}
718e3744 292
d62a17ae 293static void prefix_list_trie_del(struct prefix_list *plist,
294 struct prefix_list_entry *pentry);
295
296/* Delete prefix-list from prefix_list_master and free it. */
2fb71798 297void prefix_list_delete(struct prefix_list *plist)
d62a17ae 298{
299 struct prefix_list_list *list;
300 struct prefix_master *master;
301 struct prefix_list_entry *pentry;
302 struct prefix_list_entry *next;
303
304 /* If prefix-list contain prefix_list_entry free all of it. */
305 for (pentry = plist->head; pentry; pentry = next) {
2d26f094 306 route_map_notify_pentry_dependencies(plist->name, pentry,
49a08bb0 307 RMAP_EVENT_PLIST_DELETED);
d62a17ae 308 next = pentry->next;
309 prefix_list_trie_del(plist, pentry);
310 prefix_list_entry_free(pentry);
311 plist->count--;
312 }
718e3744 313
d62a17ae 314 master = plist->master;
718e3744 315
d62a17ae 316 if (plist->type == PREFIX_TYPE_NUMBER)
317 list = &master->num;
318 else
319 list = &master->str;
718e3744 320
d62a17ae 321 if (plist->next)
322 plist->next->prev = plist->prev;
323 else
324 list->tail = plist->prev;
718e3744 325
d62a17ae 326 if (plist->prev)
327 plist->prev->next = plist->next;
328 else
329 list->head = plist->next;
718e3744 330
0a22ddfb 331 XFREE(MTYPE_TMP, plist->desc);
718e3744 332
d62a17ae 333 /* Make sure master's recent changed prefix-list information is
334 cleared. */
335 master->recent = NULL;
518f0eb1 336
d62a17ae 337 route_map_notify_dependencies(plist->name, RMAP_EVENT_PLIST_DELETED);
518f0eb1 338
d62a17ae 339 if (master->delete_hook)
340 (*master->delete_hook)(plist);
518f0eb1 341
0a22ddfb 342 XFREE(MTYPE_MPREFIX_LIST_STR, plist->name);
7e111b6b 343
d62a17ae 344 XFREE(MTYPE_PREFIX_LIST_TRIE, plist->trie);
518f0eb1 345
d62a17ae 346 prefix_list_free(plist);
718e3744 347}
348
02ff83c5 349static struct prefix_list_entry *
d62a17ae 350prefix_list_entry_make(struct prefix *prefix, enum prefix_list_type type,
d3f6c580 351 int64_t seq, int le, int ge, bool any)
718e3744 352{
d62a17ae 353 struct prefix_list_entry *pentry;
718e3744 354
d62a17ae 355 pentry = prefix_list_entry_new();
718e3744 356
d62a17ae 357 if (any)
d3f6c580 358 pentry->any = true;
718e3744 359
d62a17ae 360 prefix_copy(&pentry->prefix, prefix);
361 pentry->type = type;
362 pentry->seq = seq;
363 pentry->le = le;
364 pentry->ge = ge;
718e3744 365
d62a17ae 366 return pentry;
718e3744 367}
368
369/* Add hook function. */
d62a17ae 370void prefix_list_add_hook(void (*func)(struct prefix_list *plist))
718e3744 371{
d62a17ae 372 prefix_master_ipv4.add_hook = func;
373 prefix_master_ipv6.add_hook = func;
718e3744 374}
375
376/* Delete hook function. */
d62a17ae 377void prefix_list_delete_hook(void (*func)(struct prefix_list *plist))
718e3744 378{
d62a17ae 379 prefix_master_ipv4.delete_hook = func;
380 prefix_master_ipv6.delete_hook = func;
718e3744 381}
382
383/* Calculate new sequential number. */
2fb71798 384int64_t prefix_new_seq_get(struct prefix_list *plist)
718e3744 385{
24512fbd
DS
386 int64_t maxseq;
387 int64_t newseq;
d62a17ae 388 struct prefix_list_entry *pentry;
718e3744 389
5037cc3e 390 maxseq = 0;
718e3744 391
d62a17ae 392 for (pentry = plist->head; pentry; pentry = pentry->next) {
393 if (maxseq < pentry->seq)
394 maxseq = pentry->seq;
395 }
718e3744 396
d62a17ae 397 newseq = ((maxseq / 5) * 5) + 5;
398
fbc7ead7 399 return (newseq > UINT_MAX) ? UINT_MAX : newseq;
718e3744 400}
401
402/* Return prefix list entry which has same seq number. */
d62a17ae 403static struct prefix_list_entry *prefix_seq_check(struct prefix_list *plist,
24512fbd 404 int64_t seq)
718e3744 405{
d62a17ae 406 struct prefix_list_entry *pentry;
718e3744 407
d62a17ae 408 for (pentry = plist->head; pentry; pentry = pentry->next)
409 if (pentry->seq == seq)
410 return pentry;
411 return NULL;
718e3744 412}
413
2fb71798 414struct prefix_list_entry *
d62a17ae 415prefix_list_entry_lookup(struct prefix_list *plist, struct prefix *prefix,
24512fbd
DS
416 enum prefix_list_type type, int64_t seq,
417 int le, int ge)
718e3744 418{
d62a17ae 419 struct prefix_list_entry *pentry;
718e3744 420
d62a17ae 421 for (pentry = plist->head; pentry; pentry = pentry->next)
422 if (prefix_same(&pentry->prefix, prefix)
423 && pentry->type == type) {
424 if (seq >= 0 && pentry->seq != seq)
425 continue;
718e3744 426
d62a17ae 427 if (pentry->le != le)
428 continue;
429 if (pentry->ge != ge)
430 continue;
718e3744 431
d62a17ae 432 return pentry;
433 }
718e3744 434
d62a17ae 435 return NULL;
718e3744 436}
437
d62a17ae 438static void trie_walk_affected(size_t validbits, struct pltrie_table *table,
439 uint8_t byte, struct prefix_list_entry *object,
440 void (*fn)(struct prefix_list_entry *object,
441 struct prefix_list_entry **updptr))
7e111b6b 442{
d62a17ae 443 uint8_t mask;
444 uint16_t bwalk;
7e111b6b 445
d62a17ae 446 if (validbits > PLC_BITS) {
447 fn(object, &table->entries[byte].final_chain);
448 return;
449 }
7e111b6b 450
d62a17ae 451 mask = (1 << (8 - validbits)) - 1;
452 for (bwalk = byte & ~mask; bwalk <= byte + mask; bwalk++) {
453 fn(object, &table->entries[bwalk].up_chain);
454 }
7e111b6b
DL
455}
456
d62a17ae 457static void trie_uninstall_fn(struct prefix_list_entry *object,
458 struct prefix_list_entry **updptr)
7e111b6b 459{
d62a17ae 460 for (; *updptr; updptr = &(*updptr)->next_best)
461 if (*updptr == object) {
462 *updptr = object->next_best;
463 break;
464 }
7e111b6b
DL
465}
466
d62a17ae 467static int trie_table_empty(struct pltrie_table *table)
7e111b6b 468{
d62a17ae 469 size_t i;
470 for (i = 0; i < PLC_LEN; i++)
471 if (table->entries[i].next_table || table->entries[i].up_chain)
472 return 0;
473 return 1;
474}
475
476static void prefix_list_trie_del(struct prefix_list *plist,
477 struct prefix_list_entry *pentry)
478{
479 size_t depth, maxdepth = plist->master->trie_depth;
9eaec2ae 480 uint8_t *bytes = pentry->prefix.u.val;
d62a17ae 481 size_t validbits = pentry->prefix.prefixlen;
482 struct pltrie_table *table, **tables[PLC_MAXLEVEL];
483
484 table = plist->trie;
485 for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) {
486 uint8_t byte = bytes[depth];
487 assert(table->entries[byte].next_table);
488
489 tables[depth + 1] = &table->entries[byte].next_table;
490 table = table->entries[byte].next_table;
491
492 validbits -= PLC_BITS;
493 }
494
495 trie_walk_affected(validbits, table, bytes[depth], pentry,
496 trie_uninstall_fn);
497
498 for (; depth > 0; depth--)
499 if (trie_table_empty(*tables[depth])) {
500 XFREE(MTYPE_PREFIX_LIST_TRIE, *tables[depth]);
d62a17ae 501 }
7e111b6b
DL
502}
503
d62a17ae 504
2fb71798
RZ
505void prefix_list_entry_delete(struct prefix_list *plist,
506 struct prefix_list_entry *pentry,
507 int update_list)
7e111b6b 508{
d62a17ae 509 if (plist == NULL || pentry == NULL)
510 return;
511
512 prefix_list_trie_del(plist, pentry);
7e111b6b 513
d62a17ae 514 if (pentry->prev)
515 pentry->prev->next = pentry->next;
516 else
517 plist->head = pentry->next;
518 if (pentry->next)
519 pentry->next->prev = pentry->prev;
520 else
521 plist->tail = pentry->prev;
7e111b6b 522
2d26f094 523 route_map_notify_pentry_dependencies(plist->name, pentry,
49a08bb0 524 RMAP_EVENT_PLIST_DELETED);
d62a17ae 525 prefix_list_entry_free(pentry);
7e111b6b 526
d62a17ae 527 plist->count--;
7e111b6b 528
d62a17ae 529 if (update_list) {
530 route_map_notify_dependencies(plist->name,
531 RMAP_EVENT_PLIST_DELETED);
532 if (plist->master->delete_hook)
533 (*plist->master->delete_hook)(plist);
7e111b6b 534
d62a17ae 535 if (plist->head == NULL && plist->tail == NULL
536 && plist->desc == NULL)
537 prefix_list_delete(plist);
538 else
539 plist->master->recent = plist;
540 }
7e111b6b
DL
541}
542
d62a17ae 543static void trie_install_fn(struct prefix_list_entry *object,
544 struct prefix_list_entry **updptr)
545{
546 while (*updptr) {
547 if (*updptr == object)
548 return;
549 if ((*updptr)->prefix.prefixlen < object->prefix.prefixlen)
550 break;
b4e55fc5
DL
551 if ((*updptr)->prefix.prefixlen == object->prefix.prefixlen
552 && (*updptr)->seq > object->seq)
d62a17ae 553 break;
554 updptr = &(*updptr)->next_best;
555 }
556
557 if (!object->next_best)
558 object->next_best = *updptr;
559 else
560 assert(object->next_best == *updptr || !*updptr);
561
562 *updptr = object;
563}
7e111b6b 564
d62a17ae 565static void prefix_list_trie_add(struct prefix_list *plist,
566 struct prefix_list_entry *pentry)
718e3744 567{
d62a17ae 568 size_t depth = plist->master->trie_depth;
9eaec2ae 569 uint8_t *bytes = pentry->prefix.u.val;
d62a17ae 570 size_t validbits = pentry->prefix.prefixlen;
571 struct pltrie_table *table;
572
573 table = plist->trie;
574 while (validbits > PLC_BITS && depth > 1) {
575 if (!table->entries[*bytes].next_table)
576 table->entries[*bytes].next_table =
577 XCALLOC(MTYPE_PREFIX_LIST_TRIE,
578 sizeof(struct pltrie_table));
579 table = table->entries[*bytes].next_table;
580 bytes++;
581 depth--;
582 validbits -= PLC_BITS;
583 }
a31ff449 584
d62a17ae 585 trie_walk_affected(validbits, table, *bytes, pentry, trie_install_fn);
586}
a31ff449 587
d62a17ae 588static void prefix_list_entry_add(struct prefix_list *plist,
589 struct prefix_list_entry *pentry)
590{
591 struct prefix_list_entry *replace;
592 struct prefix_list_entry *point;
718e3744 593
d62a17ae 594 /* Automatic asignment of seq no. */
595 if (pentry->seq == -1)
596 pentry->seq = prefix_new_seq_get(plist);
718e3744 597
d62a17ae 598 if (plist->tail && pentry->seq > plist->tail->seq)
599 point = NULL;
600 else {
601 /* Is there any same seq prefix list entry? */
602 replace = prefix_seq_check(plist, pentry->seq);
603 if (replace)
604 prefix_list_entry_delete(plist, replace, 0);
718e3744 605
d62a17ae 606 /* Check insert point. */
607 for (point = plist->head; point; point = point->next)
608 if (point->seq >= pentry->seq)
609 break;
610 }
611
612 /* In case of this is the first element of the list. */
613 pentry->next = point;
614
615 if (point) {
616 if (point->prev)
617 point->prev->next = pentry;
618 else
619 plist->head = pentry;
620
621 pentry->prev = point->prev;
622 point->prev = pentry;
623 } else {
624 if (plist->tail)
625 plist->tail->next = pentry;
626 else
627 plist->head = pentry;
628
629 pentry->prev = plist->tail;
630 plist->tail = pentry;
631 }
718e3744 632
d62a17ae 633 prefix_list_trie_add(plist, pentry);
634
635 /* Increment count. */
636 plist->count++;
637
49a08bb0
NT
638 route_map_notify_pentry_dependencies(plist->name, pentry,
639 RMAP_EVENT_PLIST_ADDED);
640
d62a17ae 641 /* Run hook function. */
642 if (plist->master->add_hook)
643 (*plist->master->add_hook)(plist);
644
645 route_map_notify_dependencies(plist->name, RMAP_EVENT_PLIST_ADDED);
718e3744 646 plist->master->recent = plist;
718e3744 647}
648
a7b28218
RZ
649/**
650 * Prefix list entry update start procedure:
744ad1af
RZ
651 * Remove entry from previosly installed master list, tries and notify
652 * observers.
a7b28218
RZ
653 *
654 * \param[in] ple prefix list entry.
655 */
656void prefix_list_entry_update_start(struct prefix_list_entry *ple)
657{
658 struct prefix_list *pl = ple->pl;
659
660 /* Not installed, nothing to do. */
661 if (!ple->installed)
662 return;
663
81b50422
RZ
664 prefix_list_trie_del(pl, ple);
665
744ad1af
RZ
666 /* List manipulation: shameless copy from `prefix_list_entry_delete`. */
667 if (ple->prev)
668 ple->prev->next = ple->next;
669 else
670 pl->head = ple->next;
671 if (ple->next)
672 ple->next->prev = ple->prev;
673 else
674 pl->tail = ple->prev;
675
a7b28218
RZ
676 route_map_notify_pentry_dependencies(pl->name, ple,
677 RMAP_EVENT_PLIST_DELETED);
678 pl->count--;
679
81b50422
RZ
680 route_map_notify_dependencies(pl->name, RMAP_EVENT_PLIST_DELETED);
681 if (pl->master->delete_hook)
682 (*pl->master->delete_hook)(pl);
683
684 if (pl->head || pl->tail || pl->desc)
685 pl->master->recent = pl;
686
f7f10115 687 ple->next_best = NULL;
a7b28218
RZ
688 ple->installed = false;
689}
690
691/**
692 * Prefix list entry update finish procedure:
744ad1af
RZ
693 * Add entry back master list, to the trie, notify observers and call master
694 * hook.
a7b28218
RZ
695 *
696 * \param[in] ple prefix list entry.
697 */
698void prefix_list_entry_update_finish(struct prefix_list_entry *ple)
699{
700 struct prefix_list *pl = ple->pl;
744ad1af 701 struct prefix_list_entry *point;
a7b28218
RZ
702
703 /* Already installed, nothing to do. */
704 if (ple->installed)
705 return;
706
81b50422
RZ
707 /*
708 * Check if the entry is installable:
709 * We can only install entry if at least the prefix is provided (IPv4
710 * or IPv6).
711 */
712 if (ple->prefix.family != AF_INET && ple->prefix.family != AF_INET6)
713 return;
714
744ad1af
RZ
715 /* List manipulation: shameless copy from `prefix_list_entry_add`. */
716 if (pl->tail && ple->seq > pl->tail->seq)
717 point = NULL;
718 else {
719 /* Check insert point. */
720 for (point = pl->head; point; point = point->next)
721 if (point->seq >= ple->seq)
722 break;
723 }
724
725 /* In case of this is the first element of the list. */
726 ple->next = point;
727
728 if (point) {
729 if (point->prev)
730 point->prev->next = ple;
731 else
732 pl->head = ple;
733
734 ple->prev = point->prev;
735 point->prev = ple;
736 } else {
737 if (pl->tail)
738 pl->tail->next = ple;
739 else
740 pl->head = ple;
741
742 ple->prev = pl->tail;
743 pl->tail = ple;
744 }
745
a7b28218
RZ
746 prefix_list_trie_add(pl, ple);
747 pl->count++;
748
749 route_map_notify_pentry_dependencies(pl->name, ple,
750 RMAP_EVENT_PLIST_ADDED);
751
752 /* Run hook function. */
753 if (pl->master->add_hook)
754 (*pl->master->add_hook)(pl);
755
756 route_map_notify_dependencies(pl->name, RMAP_EVENT_PLIST_ADDED);
757 pl->master->recent = pl;
758
759 ple->installed = true;
760}
761
81b50422
RZ
762/**
763 * Same as `prefix_list_entry_delete` but without `free()`ing the list if its
764 * empty.
765 *
766 * \param[in] ple prefix list entry.
767 */
768void prefix_list_entry_delete2(struct prefix_list_entry *ple)
769{
770 /* Does the boiler plate list removal and entry removal notification. */
771 prefix_list_entry_update_start(ple);
772
773 /* Effective `free()` memory. */
774 prefix_list_entry_free(ple);
775}
776
718e3744 777/* Return string of prefix_list_type. */
d62a17ae 778static const char *prefix_list_type_str(struct prefix_list_entry *pentry)
779{
780 switch (pentry->type) {
781 case PREFIX_PERMIT:
782 return "permit";
783 case PREFIX_DENY:
784 return "deny";
785 default:
786 return "";
787 }
788}
789
790static int prefix_list_entry_match(struct prefix_list_entry *pentry,
123214ef 791 const struct prefix *p)
d62a17ae 792{
793 int ret;
794
4f374985
DS
795 if (pentry->prefix.family != p->family)
796 return 0;
797
d62a17ae 798 ret = prefix_match(&pentry->prefix, p);
799 if (!ret)
800 return 0;
801
802 /* In case of le nor ge is specified, exact match is performed. */
803 if (!pentry->le && !pentry->ge) {
804 if (pentry->prefix.prefixlen != p->prefixlen)
805 return 0;
806 } else {
807 if (pentry->le)
808 if (p->prefixlen > pentry->le)
809 return 0;
810
811 if (pentry->ge)
812 if (p->prefixlen < pentry->ge)
813 return 0;
814 }
815 return 1;
816}
817
123214ef
MS
818enum prefix_list_type prefix_list_apply_which_prefix(
819 struct prefix_list *plist,
820 const struct prefix **which,
821 const void *object)
d62a17ae 822{
823 struct prefix_list_entry *pentry, *pbest = NULL;
824
123214ef
MS
825 const struct prefix *p = (const struct prefix *)object;
826 const uint8_t *byte = p->u.val;
d62a17ae 827 size_t depth;
828 size_t validbits = p->prefixlen;
829 struct pltrie_table *table;
830
ce94edc7
DS
831 if (plist == NULL) {
832 if (which)
833 *which = NULL;
d62a17ae 834 return PREFIX_DENY;
ce94edc7 835 }
d62a17ae 836
ce94edc7
DS
837 if (plist->count == 0) {
838 if (which)
839 *which = NULL;
d62a17ae 840 return PREFIX_PERMIT;
ce94edc7 841 }
d62a17ae 842
843 depth = plist->master->trie_depth;
844 table = plist->trie;
845 while (1) {
846 for (pentry = table->entries[*byte].up_chain; pentry;
847 pentry = pentry->next_best) {
848 if (pbest && pbest->seq < pentry->seq)
849 continue;
850 if (prefix_list_entry_match(pentry, p))
851 pbest = pentry;
852 }
853
854 if (validbits <= PLC_BITS)
855 break;
856 validbits -= PLC_BITS;
857
858 if (--depth) {
859 if (!table->entries[*byte].next_table)
860 break;
861
862 table = table->entries[*byte].next_table;
863 byte++;
864 continue;
865 }
866
867 for (pentry = table->entries[*byte].final_chain; pentry;
868 pentry = pentry->next_best) {
869 if (pbest && pbest->seq < pentry->seq)
870 continue;
871 if (prefix_list_entry_match(pentry, p))
872 pbest = pentry;
873 }
874 break;
875 }
876
ce94edc7
DS
877 if (which) {
878 if (pbest)
879 *which = &pbest->prefix;
880 else
881 *which = NULL;
882 }
883
d62a17ae 884 if (pbest == NULL)
885 return PREFIX_DENY;
886
0277936a 887 pbest->hitcnt++;
d62a17ae 888 return pbest->type;
889}
890
891static void __attribute__((unused)) prefix_list_print(struct prefix_list *plist)
892{
893 struct prefix_list_entry *pentry;
894
895 if (plist == NULL)
896 return;
897
898 printf("ip prefix-list %s: %d entries\n", plist->name, plist->count);
899
900 for (pentry = plist->head; pentry; pentry = pentry->next) {
901 if (pentry->any)
902 printf("any %s\n", prefix_list_type_str(pentry));
903 else {
904 struct prefix *p;
d62a17ae 905
906 p = &pentry->prefix;
907
b219dda1
DS
908 printf(" seq %lld %s %pFX", (long long)pentry->seq,
909 prefix_list_type_str(pentry), p);
d62a17ae 910 if (pentry->ge)
911 printf(" ge %d", pentry->ge);
912 if (pentry->le)
913 printf(" le %d", pentry->le);
914 printf("\n");
915 }
718e3744 916 }
718e3744 917}
6b0655a2 918
718e3744 919/* Retrun 1 when plist already include pentry policy. */
02ff83c5 920static struct prefix_list_entry *
d62a17ae 921prefix_entry_dup_check(struct prefix_list *plist, struct prefix_list_entry *new)
922{
923 size_t depth, maxdepth = plist->master->trie_depth;
9eaec2ae 924 uint8_t byte, *bytes = new->prefix.u.val;
d62a17ae 925 size_t validbits = new->prefix.prefixlen;
926 struct pltrie_table *table;
927 struct prefix_list_entry *pentry;
24512fbd 928 int64_t seq = 0;
d62a17ae 929
930 if (new->seq == -1)
931 seq = prefix_new_seq_get(plist);
932 else
933 seq = new->seq;
934
935 table = plist->trie;
936 for (depth = 0; validbits > PLC_BITS && depth < maxdepth - 1; depth++) {
937 byte = bytes[depth];
938 if (!table->entries[byte].next_table)
939 return NULL;
940
941 table = table->entries[byte].next_table;
942 validbits -= PLC_BITS;
718e3744 943 }
718e3744 944
d62a17ae 945 byte = bytes[depth];
946 if (validbits > PLC_BITS)
947 pentry = table->entries[byte].final_chain;
948 else
949 pentry = table->entries[byte].up_chain;
950
951 for (; pentry; pentry = pentry->next_best) {
952 if (prefix_same(&pentry->prefix, &new->prefix)
953 && pentry->type == new->type && pentry->le == new->le
954 && pentry->ge == new->ge && pentry->seq != seq)
955 return pentry;
956 }
957 return NULL;
958}
959
d62a17ae 960enum display_type {
961 normal_display,
962 summary_display,
963 detail_display,
964 sequential_display,
965 longer_display,
966 first_match_display
718e3744 967};
968
d62a17ae 969static void vty_show_prefix_entry(struct vty *vty, afi_t afi,
970 struct prefix_list *plist,
971 struct prefix_master *master,
972 enum display_type dtype, int seqnum)
973{
974 struct prefix_list_entry *pentry;
975
976 /* Print the name of the protocol */
977 vty_out(vty, "%s: ", frr_protoname);
978
979 if (dtype == normal_display) {
980 vty_out(vty, "ip%s prefix-list %s: %d entries\n",
981 afi == AFI_IP ? "" : "v6", plist->name, plist->count);
982 if (plist->desc)
983 vty_out(vty, " Description: %s\n", plist->desc);
984 } else if (dtype == summary_display || dtype == detail_display) {
985 vty_out(vty, "ip%s prefix-list %s:\n",
986 afi == AFI_IP ? "" : "v6", plist->name);
987
988 if (plist->desc)
989 vty_out(vty, " Description: %s\n", plist->desc);
990
991 vty_out(vty,
24512fbd 992 " count: %d, range entries: %d, sequences: %" PRId64 " - %" PRId64 "\n",
d62a17ae 993 plist->count, plist->rangecount,
994 plist->head ? plist->head->seq : 0,
995 plist->tail ? plist->tail->seq : 0);
718e3744 996 }
718e3744 997
d62a17ae 998 if (dtype != summary_display) {
999 for (pentry = plist->head; pentry; pentry = pentry->next) {
1000 if (dtype == sequential_display
1001 && pentry->seq != seqnum)
1002 continue;
718e3744 1003
d62a17ae 1004 vty_out(vty, " ");
718e3744 1005
d62a17ae 1006 if (master->seqnum)
24512fbd 1007 vty_out(vty, "seq %" PRId64 " ", pentry->seq);
718e3744 1008
d62a17ae 1009 vty_out(vty, "%s ", prefix_list_type_str(pentry));
718e3744 1010
d62a17ae 1011 if (pentry->any)
1012 vty_out(vty, "any");
1013 else {
1014 struct prefix *p = &pentry->prefix;
d62a17ae 1015
b219dda1 1016 vty_out(vty, "%pFX", p);
d62a17ae 1017
1018 if (pentry->ge)
1019 vty_out(vty, " ge %d", pentry->ge);
1020 if (pentry->le)
1021 vty_out(vty, " le %d", pentry->le);
1022 }
1023
1024 if (dtype == detail_display
1025 || dtype == sequential_display)
1026 vty_out(vty, " (hit count: %ld, refcount: %ld)",
1027 pentry->hitcnt, pentry->refcnt);
1028
1029 vty_out(vty, "\n");
1030 }
718e3744 1031 }
718e3744 1032}
1033
d62a17ae 1034static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name,
1035 const char *seq, enum display_type dtype)
1036{
1037 struct prefix_list *plist;
1038 struct prefix_master *master;
24512fbd 1039 int64_t seqnum = 0;
d62a17ae 1040
1041 master = prefix_master_get(afi, 0);
1042 if (master == NULL)
1043 return CMD_WARNING;
1044
1045 if (seq)
24512fbd 1046 seqnum = (int64_t)atol(seq);
d62a17ae 1047
1048 if (name) {
1049 plist = prefix_list_lookup(afi, name);
1050 if (!plist) {
1051 vty_out(vty, "%% Can't find specified prefix-list\n");
1052 return CMD_WARNING;
1053 }
1054 vty_show_prefix_entry(vty, afi, plist, master, dtype, seqnum);
1055 } else {
1056 if (dtype == detail_display || dtype == summary_display) {
1057 if (master->recent)
1058 vty_out(vty,
1059 "Prefix-list with the last deletion/insertion: %s\n",
1060 master->recent->name);
1061 }
1062
1063 for (plist = master->num.head; plist; plist = plist->next)
1064 vty_show_prefix_entry(vty, afi, plist, master, dtype,
1065 seqnum);
1066
1067 for (plist = master->str.head; plist; plist = plist->next)
1068 vty_show_prefix_entry(vty, afi, plist, master, dtype,
1069 seqnum);
1070 }
718e3744 1071
d62a17ae 1072 return CMD_SUCCESS;
1073}
718e3744 1074
d62a17ae 1075static int vty_show_prefix_list_prefix(struct vty *vty, afi_t afi,
1076 const char *name, const char *prefix,
1077 enum display_type type)
1078{
1079 struct prefix_list *plist;
1080 struct prefix_list_entry *pentry;
1081 struct prefix p;
1082 int ret;
1083 int match;
718e3744 1084
d62a17ae 1085 plist = prefix_list_lookup(afi, name);
1086 if (!plist) {
1087 vty_out(vty, "%% Can't find specified prefix-list\n");
1088 return CMD_WARNING;
718e3744 1089 }
1090
d62a17ae 1091 ret = str2prefix(prefix, &p);
1092 if (ret <= 0) {
1093 vty_out(vty, "%% prefix is malformed\n");
1094 return CMD_WARNING;
718e3744 1095 }
1096
d62a17ae 1097 for (pentry = plist->head; pentry; pentry = pentry->next) {
1098 match = 0;
1099
1100 if (type == normal_display || type == first_match_display)
1101 if (prefix_same(&p, &pentry->prefix))
1102 match = 1;
1103
4f374985 1104 if (type == longer_display) {
996c9314
LB
1105 if ((p.family == pentry->prefix.family)
1106 && (prefix_match(&p, &pentry->prefix)))
d62a17ae 1107 match = 1;
4f374985 1108 }
d62a17ae 1109
1110 if (match) {
24512fbd 1111 vty_out(vty, " seq %" PRId64 " %s ", pentry->seq,
d62a17ae 1112 prefix_list_type_str(pentry));
1113
1114 if (pentry->any)
1115 vty_out(vty, "any");
1116 else {
7fe96307 1117 struct prefix *pf = &pentry->prefix;
d62a17ae 1118
b219dda1 1119 vty_out(vty, "%pFX", pf);
d62a17ae 1120
1121 if (pentry->ge)
1122 vty_out(vty, " ge %d", pentry->ge);
1123 if (pentry->le)
1124 vty_out(vty, " le %d", pentry->le);
1125 }
1126
1127 if (type == normal_display
1128 || type == first_match_display)
1129 vty_out(vty, " (hit count: %ld, refcount: %ld)",
1130 pentry->hitcnt, pentry->refcnt);
1131
1132 vty_out(vty, "\n");
1133
1134 if (type == first_match_display)
1135 return CMD_SUCCESS;
1136 }
718e3744 1137 }
d62a17ae 1138 return CMD_SUCCESS;
1139}
1140
1141static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name,
1142 const char *prefix)
1143{
1144 struct prefix_master *master;
1145 struct prefix_list *plist;
1146 struct prefix_list_entry *pentry;
1147 int ret;
1148 struct prefix p;
1149
1150 master = prefix_master_get(afi, 0);
1151 if (master == NULL)
1152 return CMD_WARNING;
1153
1154 if (name == NULL && prefix == NULL) {
1155 for (plist = master->num.head; plist; plist = plist->next)
1156 for (pentry = plist->head; pentry;
1157 pentry = pentry->next)
1158 pentry->hitcnt = 0;
1159
1160 for (plist = master->str.head; plist; plist = plist->next)
1161 for (pentry = plist->head; pentry;
1162 pentry = pentry->next)
1163 pentry->hitcnt = 0;
1164 } else {
1165 plist = prefix_list_lookup(afi, name);
1166 if (!plist) {
1167 vty_out(vty, "%% Can't find specified prefix-list\n");
1168 return CMD_WARNING;
1169 }
1170
1171 if (prefix) {
1172 ret = str2prefix(prefix, &p);
1173 if (ret <= 0) {
1174 vty_out(vty, "%% prefix is malformed\n");
1175 return CMD_WARNING;
1176 }
1177 }
1178
1179 for (pentry = plist->head; pentry; pentry = pentry->next) {
1180 if (prefix) {
996c9314
LB
1181 if (pentry->prefix.family == p.family
1182 && prefix_match(&pentry->prefix, &p))
d62a17ae 1183 pentry->hitcnt = 0;
1184 } else
1185 pentry->hitcnt = 0;
1186 }
1187 }
1188 return CMD_SUCCESS;
718e3744 1189}
6b0655a2 1190
6cdff321 1191#ifndef VTYSH_EXTRACT_PL
2e4c2296 1192#include "lib/plist_clippy.c"
6cdff321
DL
1193#endif
1194
6cdff321
DL
1195DEFPY (ip_prefix_list_sequence_number,
1196 ip_prefix_list_sequence_number_cmd,
1197 "[no] ip prefix-list sequence-number",
718e3744 1198 NO_STR
6cdff321 1199 IP_STR
718e3744 1200 PREFIX_LIST_STR
6cdff321 1201 "Include/exclude sequence numbers in NVGEN\n")
718e3744 1202{
e11d84ad 1203 prefix_master_ipv4.seqnum = no ? false : true;
d62a17ae 1204 return CMD_SUCCESS;
718e3744 1205}
1206
718e3744 1207
6cdff321
DL
1208DEFPY (show_ip_prefix_list,
1209 show_ip_prefix_list_cmd,
1210 "show ip prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
1211 SHOW_STR
1212 IP_STR
718e3744 1213 PREFIX_LIST_STR
1214 "Name of a prefix list\n"
6cdff321
DL
1215 "sequence number of an entry\n"
1216 "Sequence number\n")
718e3744 1217{
d62a17ae 1218 enum display_type dtype = normal_display;
1219 if (dseq)
1220 dtype = sequential_display;
6cdff321 1221
d62a17ae 1222 return vty_show_prefix_list(vty, AFI_IP, prefix_list, arg_str, dtype);
718e3744 1223}
1224
6cdff321
DL
1225DEFPY (show_ip_prefix_list_prefix,
1226 show_ip_prefix_list_prefix_cmd,
1227 "show ip prefix-list WORD A.B.C.D/M$prefix [longer$dl|first-match$dfm]",
1228 SHOW_STR
1229 IP_STR
718e3744 1230 PREFIX_LIST_STR
1231 "Name of a prefix list\n"
6cdff321
DL
1232 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1233 "Lookup longer prefix\n"
1234 "First matched prefix\n")
718e3744 1235{
d62a17ae 1236 enum display_type dtype = normal_display;
1237 if (dl)
1238 dtype = longer_display;
1239 else if (dfm)
1240 dtype = first_match_display;
6cdff321 1241
d62a17ae 1242 return vty_show_prefix_list_prefix(vty, AFI_IP, prefix_list, prefix_str,
1243 dtype);
718e3744 1244}
1245
6cdff321
DL
1246DEFPY (show_ip_prefix_list_summary,
1247 show_ip_prefix_list_summary_cmd,
1248 "show ip prefix-list summary [WORD$prefix_list]",
1249 SHOW_STR
1250 IP_STR
718e3744 1251 PREFIX_LIST_STR
6cdff321
DL
1252 "Summary of prefix lists\n"
1253 "Name of a prefix list\n")
718e3744 1254{
d62a17ae 1255 return vty_show_prefix_list(vty, AFI_IP, prefix_list, NULL,
1256 summary_display);
718e3744 1257}
1258
6cdff321
DL
1259DEFPY (show_ip_prefix_list_detail,
1260 show_ip_prefix_list_detail_cmd,
1261 "show ip prefix-list detail [WORD$prefix_list]",
1262 SHOW_STR
1263 IP_STR
1264 PREFIX_LIST_STR
1265 "Detail of prefix lists\n"
1266 "Name of a prefix list\n")
1267{
d62a17ae 1268 return vty_show_prefix_list(vty, AFI_IP, prefix_list, NULL,
1269 detail_display);
6cdff321
DL
1270}
1271
1272DEFPY (clear_ip_prefix_list,
1273 clear_ip_prefix_list_cmd,
1274 "clear ip prefix-list [WORD [A.B.C.D/M$prefix]]",
1275 CLEAR_STR
1276 IP_STR
718e3744 1277 PREFIX_LIST_STR
1278 "Name of a prefix list\n"
6cdff321 1279 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
718e3744 1280{
d62a17ae 1281 return vty_clear_prefix_list(vty, AFI_IP, prefix_list, prefix_str);
6cdff321
DL
1282}
1283
6cdff321
DL
1284DEFPY (ipv6_prefix_list_sequence_number,
1285 ipv6_prefix_list_sequence_number_cmd,
1286 "[no] ipv6 prefix-list sequence-number",
718e3744 1287 NO_STR
1288 IPV6_STR
1289 PREFIX_LIST_STR
1290 "Include/exclude sequence numbers in NVGEN\n")
1291{
e11d84ad 1292 prefix_master_ipv6.seqnum = no ? false : true;
d62a17ae 1293 return CMD_SUCCESS;
718e3744 1294}
1295
6cdff321 1296DEFPY (show_ipv6_prefix_list,
718e3744 1297 show_ipv6_prefix_list_cmd,
6cdff321 1298 "show ipv6 prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
718e3744 1299 SHOW_STR
1300 IPV6_STR
1301 PREFIX_LIST_STR
1302 "Name of a prefix list\n"
1303 "sequence number of an entry\n"
7111c1a0 1304 "Sequence number\n")
718e3744 1305{
d62a17ae 1306 enum display_type dtype = normal_display;
1307 if (dseq)
1308 dtype = sequential_display;
718e3744 1309
d62a17ae 1310 return vty_show_prefix_list(vty, AFI_IP6, prefix_list, arg_str, dtype);
718e3744 1311}
1312
6cdff321
DL
1313DEFPY (show_ipv6_prefix_list_prefix,
1314 show_ipv6_prefix_list_prefix_cmd,
1315 "show ipv6 prefix-list WORD X:X::X:X/M$prefix [longer$dl|first-match$dfm]",
718e3744 1316 SHOW_STR
1317 IPV6_STR
1318 PREFIX_LIST_STR
1319 "Name of a prefix list\n"
1320 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
6cdff321 1321 "Lookup longer prefix\n"
718e3744 1322 "First matched prefix\n")
1323{
d62a17ae 1324 enum display_type dtype = normal_display;
1325 if (dl)
1326 dtype = longer_display;
1327 else if (dfm)
1328 dtype = first_match_display;
718e3744 1329
d62a17ae 1330 return vty_show_prefix_list_prefix(vty, AFI_IP6, prefix_list,
1331 prefix_str, dtype);
718e3744 1332}
1333
6cdff321
DL
1334DEFPY (show_ipv6_prefix_list_summary,
1335 show_ipv6_prefix_list_summary_cmd,
1336 "show ipv6 prefix-list summary [WORD$prefix-list]",
718e3744 1337 SHOW_STR
1338 IPV6_STR
1339 PREFIX_LIST_STR
1340 "Summary of prefix lists\n"
1341 "Name of a prefix list\n")
1342{
d62a17ae 1343 return vty_show_prefix_list(vty, AFI_IP6, prefix_list, NULL,
1344 summary_display);
718e3744 1345}
1346
6cdff321 1347DEFPY (show_ipv6_prefix_list_detail,
718e3744 1348 show_ipv6_prefix_list_detail_cmd,
6cdff321 1349 "show ipv6 prefix-list detail [WORD$prefix-list]",
718e3744 1350 SHOW_STR
1351 IPV6_STR
1352 PREFIX_LIST_STR
1353 "Detail of prefix lists\n"
1354 "Name of a prefix list\n")
1355{
d62a17ae 1356 return vty_show_prefix_list(vty, AFI_IP6, prefix_list, NULL,
1357 detail_display);
718e3744 1358}
1359
6cdff321 1360DEFPY (clear_ipv6_prefix_list,
718e3744 1361 clear_ipv6_prefix_list_cmd,
6cdff321 1362 "clear ipv6 prefix-list [WORD [X:X::X:X/M$prefix]]",
718e3744 1363 CLEAR_STR
1364 IPV6_STR
1365 PREFIX_LIST_STR
1366 "Name of a prefix list\n"
1367 "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
1368{
d62a17ae 1369 return vty_clear_prefix_list(vty, AFI_IP6, prefix_list, prefix_str);
718e3744 1370}
6b0655a2 1371
d62a17ae 1372struct stream *prefix_bgp_orf_entry(struct stream *s, struct prefix_list *plist,
d7c0a89a
QY
1373 uint8_t init_flag, uint8_t permit_flag,
1374 uint8_t deny_flag)
718e3744 1375{
d62a17ae 1376 struct prefix_list_entry *pentry;
718e3744 1377
d62a17ae 1378 if (!plist)
1379 return s;
718e3744 1380
d62a17ae 1381 for (pentry = plist->head; pentry; pentry = pentry->next) {
d7c0a89a 1382 uint8_t flag = init_flag;
d62a17ae 1383 struct prefix *p = &pentry->prefix;
718e3744 1384
d62a17ae 1385 flag |= (pentry->type == PREFIX_PERMIT ? permit_flag
1386 : deny_flag);
1387 stream_putc(s, flag);
d7c0a89a
QY
1388 stream_putl(s, (uint32_t)pentry->seq);
1389 stream_putc(s, (uint8_t)pentry->ge);
1390 stream_putc(s, (uint8_t)pentry->le);
d62a17ae 1391 stream_put_prefix(s, p);
1392 }
718e3744 1393
d62a17ae 1394 return s;
718e3744 1395}
1396
d62a17ae 1397int prefix_bgp_orf_set(char *name, afi_t afi, struct orf_prefix *orfp,
1398 int permit, int set)
718e3744 1399{
d62a17ae 1400 struct prefix_list *plist;
1401 struct prefix_list_entry *pentry;
718e3744 1402
d62a17ae 1403 /* ge and le value check */
1404 if (orfp->ge && orfp->ge <= orfp->p.prefixlen)
1405 return CMD_WARNING_CONFIG_FAILED;
1406 if (orfp->le && orfp->le <= orfp->p.prefixlen)
1407 return CMD_WARNING_CONFIG_FAILED;
1408 if (orfp->le && orfp->ge > orfp->le)
1409 return CMD_WARNING_CONFIG_FAILED;
718e3744 1410
d62a17ae 1411 if (orfp->ge && orfp->le == (afi == AFI_IP ? 32 : 128))
1412 orfp->le = 0;
718e3744 1413
d62a17ae 1414 plist = prefix_list_get(afi, 1, name);
1415 if (!plist)
1416 return CMD_WARNING_CONFIG_FAILED;
718e3744 1417
3dbedfbd
QY
1418 apply_mask(&orfp->p);
1419
d62a17ae 1420 if (set) {
1421 pentry = prefix_list_entry_make(
1422 &orfp->p, (permit ? PREFIX_PERMIT : PREFIX_DENY),
d3f6c580 1423 orfp->seq, orfp->le, orfp->ge, false);
718e3744 1424
d62a17ae 1425 if (prefix_entry_dup_check(plist, pentry)) {
1426 prefix_list_entry_free(pentry);
1427 return CMD_WARNING_CONFIG_FAILED;
1428 }
718e3744 1429
d62a17ae 1430 prefix_list_entry_add(plist, pentry);
1431 } else {
1432 pentry = prefix_list_entry_lookup(
1433 plist, &orfp->p, (permit ? PREFIX_PERMIT : PREFIX_DENY),
1434 orfp->seq, orfp->le, orfp->ge);
718e3744 1435
d62a17ae 1436 if (!pentry)
1437 return CMD_WARNING_CONFIG_FAILED;
718e3744 1438
d62a17ae 1439 prefix_list_entry_delete(plist, pentry, 1);
1440 }
718e3744 1441
d62a17ae 1442 return CMD_SUCCESS;
718e3744 1443}
1444
d62a17ae 1445void prefix_bgp_orf_remove_all(afi_t afi, char *name)
718e3744 1446{
d62a17ae 1447 struct prefix_list *plist;
718e3744 1448
d62a17ae 1449 plist = prefix_bgp_orf_lookup(afi, name);
1450 if (plist)
1451 prefix_list_delete(plist);
718e3744 1452}
1453
1454/* return prefix count */
d62a17ae 1455int prefix_bgp_show_prefix_list(struct vty *vty, afi_t afi, char *name,
9f049418 1456 bool use_json)
d62a17ae 1457{
1458 struct prefix_list *plist;
1459 struct prefix_list_entry *pentry;
1460 json_object *json = NULL;
1461 json_object *json_prefix = NULL;
1462 json_object *json_list = NULL;
1463
1464 plist = prefix_bgp_orf_lookup(afi, name);
1465 if (!plist)
1466 return 0;
1467
1468 if (!vty)
1469 return plist->count;
1470
1471 if (use_json) {
1472 json = json_object_new_object();
1473 json_prefix = json_object_new_object();
1474 json_list = json_object_new_object();
1475
1476 json_object_int_add(json_prefix, "prefixListCounter",
1477 plist->count);
1478 json_object_string_add(json_prefix, "prefixListName",
1479 plist->name);
1480
1481 for (pentry = plist->head; pentry; pentry = pentry->next) {
1482 struct prefix *p = &pentry->prefix;
1483 char buf_a[BUFSIZ];
d62a17ae 1484
b219dda1 1485 snprintf(buf_a, sizeof(buf_a), "%pFX", p);
d62a17ae 1486
1487 json_object_int_add(json_list, "seq", pentry->seq);
1488 json_object_string_add(json_list, "seqPrefixListType",
1489 prefix_list_type_str(pentry));
1490
1491 if (pentry->ge)
1492 json_object_int_add(json_list, "ge",
1493 pentry->ge);
1494 if (pentry->le)
1495 json_object_int_add(json_list, "le",
1496 pentry->le);
1497
1498 json_object_object_add(json_prefix, buf_a, json_list);
1499 }
1500 if (afi == AFI_IP)
1501 json_object_object_add(json, "ipPrefixList",
1502 json_prefix);
1503 else
1504 json_object_object_add(json, "ipv6PrefixList",
1505 json_prefix);
1506
9d303b37
DL
1507 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1508 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 1509 json_object_free(json);
1510 } else {
1511 vty_out(vty, "ip%s prefix-list %s: %d entries\n",
1512 afi == AFI_IP ? "" : "v6", plist->name, plist->count);
1513
1514 for (pentry = plist->head; pentry; pentry = pentry->next) {
1515 struct prefix *p = &pentry->prefix;
d62a17ae 1516
b219dda1
DS
1517 vty_out(vty, " seq %" PRId64 " %s %pFX", pentry->seq,
1518 prefix_list_type_str(pentry), p);
d62a17ae 1519
1520 if (pentry->ge)
1521 vty_out(vty, " ge %d", pentry->ge);
1522 if (pentry->le)
1523 vty_out(vty, " le %d", pentry->le);
1524
1525 vty_out(vty, "\n");
1526 }
1527 }
1528 return plist->count;
1529}
1530
1531static void prefix_list_reset_afi(afi_t afi, int orf)
1532{
1533 struct prefix_list *plist;
1534 struct prefix_list *next;
1535 struct prefix_master *master;
1536
1537 master = prefix_master_get(afi, orf);
1538 if (master == NULL)
1539 return;
1540
1541 for (plist = master->num.head; plist; plist = next) {
1542 next = plist->next;
1543 prefix_list_delete(plist);
1544 }
1545 for (plist = master->str.head; plist; plist = next) {
1546 next = plist->next;
1547 prefix_list_delete(plist);
1548 }
1549
1550 assert(master->num.head == NULL);
1551 assert(master->num.tail == NULL);
1552
1553 assert(master->str.head == NULL);
1554 assert(master->str.tail == NULL);
1555
08c2d52a 1556 master->seqnum = true;
d62a17ae 1557 master->recent = NULL;
718e3744 1558}
1559
718e3744 1560/* Prefix-list node. */
62b346ee 1561static struct cmd_node prefix_node = {
f4b8291f 1562 .name = "ipv4 prefix list",
62b346ee
DL
1563 .node = PREFIX_NODE,
1564 .prompt = "",
62b346ee 1565};
718e3744 1566
d62a17ae 1567static void plist_autocomplete_afi(afi_t afi, vector comps,
1568 struct cmd_token *token)
70d44c5c 1569{
d62a17ae 1570 struct prefix_list *plist;
1571 struct prefix_master *master;
70d44c5c 1572
d62a17ae 1573 master = prefix_master_get(afi, 0);
1574 if (master == NULL)
1575 return;
70d44c5c 1576
d62a17ae 1577 for (plist = master->str.head; plist; plist = plist->next)
1578 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, plist->name));
1579 for (plist = master->num.head; plist; plist = plist->next)
1580 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, plist->name));
70d44c5c
DL
1581}
1582
d62a17ae 1583static void plist_autocomplete(vector comps, struct cmd_token *token)
70d44c5c 1584{
d62a17ae 1585 plist_autocomplete_afi(AFI_IP, comps, token);
1586 plist_autocomplete_afi(AFI_IP6, comps, token);
70d44c5c
DL
1587}
1588
1589static const struct cmd_variable_handler plist_var_handlers[] = {
d62a17ae 1590 {/* "prefix-list WORD" */
1591 .varname = "prefix_list",
1592 .completions = plist_autocomplete},
1593 {.completions = NULL}};
70d44c5c
DL
1594
1595
d62a17ae 1596static void prefix_list_init_ipv4(void)
718e3744 1597{
612c2c15 1598 install_node(&prefix_node);
718e3744 1599
d62a17ae 1600 install_element(CONFIG_NODE, &ip_prefix_list_sequence_number_cmd);
718e3744 1601
d62a17ae 1602 install_element(VIEW_NODE, &show_ip_prefix_list_cmd);
1603 install_element(VIEW_NODE, &show_ip_prefix_list_prefix_cmd);
1604 install_element(VIEW_NODE, &show_ip_prefix_list_summary_cmd);
1605 install_element(VIEW_NODE, &show_ip_prefix_list_detail_cmd);
718e3744 1606
d62a17ae 1607 install_element(ENABLE_NODE, &clear_ip_prefix_list_cmd);
718e3744 1608}
1609
718e3744 1610/* Prefix-list node. */
d62a17ae 1611static struct cmd_node prefix_ipv6_node = {
f4b8291f 1612 .name = "ipv6 prefix list",
62b346ee
DL
1613 .node = PREFIX_IPV6_NODE,
1614 .prompt = "",
62b346ee 1615};
718e3744 1616
d62a17ae 1617static void prefix_list_init_ipv6(void)
718e3744 1618{
612c2c15 1619 install_node(&prefix_ipv6_node);
718e3744 1620
d62a17ae 1621 install_element(CONFIG_NODE, &ipv6_prefix_list_sequence_number_cmd);
718e3744 1622
d62a17ae 1623 install_element(VIEW_NODE, &show_ipv6_prefix_list_cmd);
1624 install_element(VIEW_NODE, &show_ipv6_prefix_list_prefix_cmd);
1625 install_element(VIEW_NODE, &show_ipv6_prefix_list_summary_cmd);
1626 install_element(VIEW_NODE, &show_ipv6_prefix_list_detail_cmd);
718e3744 1627
d62a17ae 1628 install_element(ENABLE_NODE, &clear_ipv6_prefix_list_cmd);
718e3744 1629}
718e3744 1630
4d762f26 1631void prefix_list_init(void)
718e3744 1632{
d62a17ae 1633 cmd_variable_handler_register(plist_var_handlers);
70d44c5c 1634
d62a17ae 1635 prefix_list_init_ipv4();
1636 prefix_list_init_ipv6();
718e3744 1637}
1638
4d762f26 1639void prefix_list_reset(void)
718e3744 1640{
d62a17ae 1641 prefix_list_reset_afi(AFI_IP, 0);
1642 prefix_list_reset_afi(AFI_IP6, 0);
1643 prefix_list_reset_afi(AFI_IP, 1);
1644 prefix_list_reset_afi(AFI_IP6, 1);
718e3744 1645}