]> git.proxmox.com Git - mirror_frr.git/blame - pbrd/pbr_map.c
*: make frr_yang_module_info const
[mirror_frr.git] / pbrd / pbr_map.c
CommitLineData
e5c83d9b
DS
1/*
2 * PBR-map Code
3 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
6 * FRR is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * FRR 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 *
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
19 */
20#include <zebra.h>
21
22#include "thread.h"
23#include "linklist.h"
24#include "prefix.h"
25#include "table.h"
26#include "vrf.h"
27#include "nexthop.h"
28#include "nexthop_group.h"
29#include "memory.h"
30#include "log.h"
31#include "vty.h"
32
33#include "pbr_nht.h"
34#include "pbr_map.h"
e5c83d9b
DS
35#include "pbr_zebra.h"
36#include "pbr_memory.h"
37#include "pbr_debug.h"
be3b67b5 38#include "pbr_vrf.h"
e5c83d9b
DS
39
40DEFINE_MTYPE_STATIC(PBRD, PBR_MAP, "PBR Map")
41DEFINE_MTYPE_STATIC(PBRD, PBR_MAP_SEQNO, "PBR Map Sequence")
42DEFINE_MTYPE_STATIC(PBRD, PBR_MAP_INTERFACE, "PBR Map Interface")
43
44static uint32_t pbr_map_sequence_unique;
45
be3b67b5 46static bool pbr_map_check_valid_internal(struct pbr_map *pbrm);
d3765386
DS
47static inline int pbr_map_compare(const struct pbr_map *pbrmap1,
48 const struct pbr_map *pbrmap2);
e5c83d9b
DS
49
50RB_GENERATE(pbr_map_entry_head, pbr_map, pbr_map_entry, pbr_map_compare)
51
52struct pbr_map_entry_head pbr_maps = RB_INITIALIZER(&pbr_maps);
53
54DEFINE_QOBJ_TYPE(pbr_map_sequence)
55
d3765386
DS
56static inline int pbr_map_compare(const struct pbr_map *pbrmap1,
57 const struct pbr_map *pbrmap2)
e5c83d9b
DS
58{
59 return strcmp(pbrmap1->name, pbrmap2->name);
60}
61
62static int pbr_map_sequence_compare(const struct pbr_map_sequence *pbrms1,
63 const struct pbr_map_sequence *pbrms2)
64{
65 if (pbrms1->seqno == pbrms2->seqno)
66 return 0;
67
68 if (pbrms1->seqno < pbrms2->seqno)
69 return -1;
70
71 return 1;
72}
73
74static void pbr_map_sequence_delete(struct pbr_map_sequence *pbrms)
75{
0a22ddfb 76 XFREE(MTYPE_TMP, pbrms->internal_nhg_name);
e5c83d9b
DS
77
78 XFREE(MTYPE_PBR_MAP_SEQNO, pbrms);
79}
80
81static int pbr_map_interface_compare(const struct pbr_map_interface *pmi1,
82 const struct pbr_map_interface *pmi2)
83{
84 return strcmp(pmi1->ifp->name, pmi2->ifp->name);
85}
86
b13e5ad6 87static void pbr_map_interface_list_delete(struct pbr_map_interface *pmi)
e5c83d9b 88{
b13e5ad6
DS
89 struct pbr_map_interface *pmi_int;
90 struct listnode *node, *nnode;
91 struct pbr_map *pbrm;
92
93 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
94 for (ALL_LIST_ELEMENTS(pbrm->incoming, node, nnode, pmi_int)) {
95 if (pmi == pmi_int) {
96 pbr_map_policy_delete(pbrm, pmi);
97 return;
98 }
99 }
100 }
e5c83d9b
DS
101}
102
be3b67b5
SW
103static bool pbr_map_interface_is_valid(const struct pbr_map_interface *pmi)
104{
105 /* Don't install rules without a real ifindex on the incoming interface.
106 *
107 * This can happen when we have config for an interface that does not
108 * exist or when an interface is changing vrfs.
109 */
110 if (pmi->ifp && pmi->ifp->ifindex != IFINDEX_INTERNAL)
111 return true;
112
113 return false;
114}
115
116static void pbr_map_pbrms_update_common(struct pbr_map_sequence *pbrms,
117 bool install)
118{
119 struct pbr_map *pbrm;
120 struct listnode *node;
121 struct pbr_map_interface *pmi;
122
123 pbrm = pbrms->parent;
124
125 if (pbrms->nhs_installed && pbrm->incoming->count) {
126 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) {
127 if (!pmi->ifp)
128 continue;
129
130 if (install && !pbr_map_interface_is_valid(pmi))
131 continue;
132
133 pbr_send_pbr_map(pbrms, pmi, install);
134 }
135 }
136}
137
138static void pbr_map_pbrms_install(struct pbr_map_sequence *pbrms)
139{
140 pbr_map_pbrms_update_common(pbrms, true);
141}
142
143static void pbr_map_pbrms_uninstall(struct pbr_map_sequence *pbrms)
144{
145 pbr_map_pbrms_update_common(pbrms, false);
146}
147
e5c83d9b
DS
148static const char *pbr_map_reason_str[] = {
149 "Invalid NH-group", "Invalid NH", "No Nexthops",
be3b67b5
SW
150 "Both NH and NH-Group", "Invalid Src or Dst", "Invalid VRF",
151 "Deleting Sequence",
e5c83d9b
DS
152};
153
154void pbr_map_reason_string(unsigned int reason, char *buf, int size)
155{
156 unsigned int bit;
157 int len = 0;
158
159 if (!buf)
160 return;
161
162 for (bit = 0; bit < array_size(pbr_map_reason_str); bit++) {
163 if ((reason & (1 << bit)) && (len < size)) {
164 len += snprintf((buf + len), (size - len), "%s%s",
165 (len > 0) ? ", " : "",
166 pbr_map_reason_str[bit]);
167 }
168 }
169}
170
38e9ccde
DS
171void pbr_map_final_interface_deletion(struct pbr_map *pbrm,
172 struct pbr_map_interface *pmi)
173{
174 if (pmi->delete == true) {
175 listnode_delete(pbrm->incoming, pmi);
176 pmi->pbrm = NULL;
177
178 bf_release_index(pbrm->ifi_bitfield, pmi->install_bit);
179 XFREE(MTYPE_PBR_MAP_INTERFACE, pmi);
180 }
181}
e5c83d9b
DS
182
183void pbr_map_interface_delete(struct pbr_map *pbrm, struct interface *ifp_del)
184{
185
186 struct listnode *node;
187 struct pbr_map_interface *pmi;
e5c83d9b
DS
188
189 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) {
190 if (ifp_del == pmi->ifp)
191 break;
192 }
193
b13e5ad6
DS
194 if (pmi)
195 pbr_map_policy_delete(pbrm, pmi);
e5c83d9b
DS
196}
197
198void pbr_map_add_interface(struct pbr_map *pbrm, struct interface *ifp_add)
199{
200 struct listnode *node;
201 struct pbr_map_interface *pmi;
e5c83d9b
DS
202
203 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) {
204 if (ifp_add == pmi->ifp)
205 return;
206 }
207
208 pmi = XCALLOC(MTYPE_PBR_MAP_INTERFACE, sizeof(*pmi));
209 pmi->ifp = ifp_add;
210 pmi->pbrm = pbrm;
211 listnode_add_sort(pbrm->incoming, pmi);
212
37c606ff 213 bf_assign_index(pbrm->ifi_bitfield, pmi->install_bit);
b13e5ad6 214 pbr_map_check_valid(pbrm->name);
d02e9432 215 if (pbrm->valid)
b13e5ad6 216 pbr_map_install(pbrm);
e5c83d9b
DS
217}
218
be3b67b5
SW
219static int
220pbr_map_policy_interface_update_common(const struct interface *ifp,
221 struct pbr_interface **pbr_ifp,
222 struct pbr_map **pbrm)
223{
224 if (!ifp->info) {
225 DEBUGD(&pbr_dbg_map, "%s: %s has no pbr_interface info",
226 __func__, ifp->name);
227 return -1;
228 }
229
230 *pbr_ifp = ifp->info;
231
232 *pbrm = pbrm_find((*pbr_ifp)->mapname);
233
234 if (!*pbrm) {
235 DEBUGD(&pbr_dbg_map, "%s: applied PBR-MAP(%s) does not exist?",
236 __func__, (*pbr_ifp)->mapname);
237 return -1;
238 }
239
240 return 0;
241}
242
243void pbr_map_policy_interface_update(const struct interface *ifp, bool state_up)
244{
245 struct pbr_interface *pbr_ifp;
246 struct pbr_map_sequence *pbrms;
247 struct pbr_map *pbrm;
248 struct listnode *node, *inode;
249 struct pbr_map_interface *pmi;
250
251 if (pbr_map_policy_interface_update_common(ifp, &pbr_ifp, &pbrm))
252 return;
253
254 DEBUGD(&pbr_dbg_map, "%s: %s %s rules on interface %s", __func__,
255 pbr_ifp->mapname, (state_up ? "installing" : "removing"),
256 ifp->name);
257
258 /*
259 * Walk the list and install/remove maps on the interface.
260 */
261 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
262 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
263 if (pmi->ifp == ifp && pbr_map_interface_is_valid(pmi))
264 pbr_send_pbr_map(pbrms, pmi, state_up);
265}
266
267static void pbrms_vrf_update(struct pbr_map_sequence *pbrms,
268 const struct pbr_vrf *pbr_vrf)
269{
270 const char *vrf_name = pbr_vrf_name(pbr_vrf);
271
272 if (pbrms->vrf_lookup
273 && (strncmp(vrf_name, pbrms->vrf_name, sizeof(pbrms->vrf_name))
274 == 0)) {
275 DEBUGD(&pbr_dbg_map, "\tSeq %u uses vrf %s (%u), updating map",
276 pbrms->seqno, vrf_name, pbr_vrf_id(pbr_vrf));
277
278 pbr_map_check(pbrms);
279 }
280}
281
282/* Vrf enabled/disabled */
283void pbr_map_vrf_update(const struct pbr_vrf *pbr_vrf)
284{
285 struct pbr_map *pbrm;
286 struct pbr_map_sequence *pbrms;
287 struct listnode *node;
288
289 if (!pbr_vrf)
290 return;
291
292 bool enabled = pbr_vrf_is_enabled(pbr_vrf);
293
294 DEBUGD(&pbr_dbg_map, "%s: %s (%u) %s, updating pbr maps", __func__,
295 pbr_vrf_name(pbr_vrf), pbr_vrf_id(pbr_vrf),
296 enabled ? "enabled" : "disabled");
297
298 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
299 DEBUGD(&pbr_dbg_map, "%s: Looking at %s", __PRETTY_FUNCTION__,
300 pbrm->name);
301 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
302 pbrms_vrf_update(pbrms, pbr_vrf);
303 }
304}
305
e5c83d9b
DS
306void pbr_map_write_interfaces(struct vty *vty, struct interface *ifp)
307{
308 struct pbr_interface *pbr_ifp = ifp->info;
309
f1c3fe1b
QY
310 if (pbr_ifp
311 && strncmp(pbr_ifp->mapname, "", sizeof(pbr_ifp->mapname)) != 0)
e5c83d9b
DS
312 vty_out(vty, " pbr-policy %s\n", pbr_ifp->mapname);
313}
314
315struct pbr_map *pbrm_find(const char *name)
316{
317 struct pbr_map pbrm;
318
319 strlcpy(pbrm.name, name, sizeof(pbrm.name));
320
321 return RB_FIND(pbr_map_entry_head, &pbr_maps, &pbrm);
322}
323
b13e5ad6 324extern void pbr_map_delete(struct pbr_map_sequence *pbrms)
e5c83d9b
DS
325{
326 struct pbr_map *pbrm;
b13e5ad6
DS
327 struct listnode *inode;
328 struct pbr_map_interface *pmi;
e5c83d9b 329
b13e5ad6 330 pbrm = pbrms->parent;
e5c83d9b 331
b13e5ad6
DS
332 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
333 pbr_send_pbr_map(pbrms, pmi, false);
e5c83d9b 334
b13e5ad6
DS
335 if (pbrms->nhg)
336 pbr_nht_delete_individual_nexthop(pbrms);
e5c83d9b 337
b13e5ad6 338 listnode_delete(pbrm->seqnumbers, pbrms);
e5c83d9b
DS
339
340 if (pbrm->seqnumbers->count == 0) {
341 RB_REMOVE(pbr_map_entry_head, &pbr_maps, pbrm);
37c606ff
DS
342
343 bf_free(pbrm->ifi_bitfield);
e5c83d9b
DS
344 XFREE(MTYPE_PBR_MAP, pbrm);
345 }
346}
347
be3b67b5 348static void pbr_map_delete_common(struct pbr_map_sequence *pbrms)
b13e5ad6
DS
349{
350 struct pbr_map *pbrm = pbrms->parent;
b13e5ad6 351
be3b67b5 352 pbr_map_pbrms_uninstall(pbrms);
b13e5ad6
DS
353
354 pbrm->valid = false;
355 pbrms->nhs_installed = false;
b13e5ad6
DS
356 pbrms->reason |= PBR_MAP_INVALID_NO_NEXTHOPS;
357 pbrms->nhgrp_name = NULL;
358}
359
be3b67b5
SW
360void pbr_map_delete_nexthops(struct pbr_map_sequence *pbrms)
361{
362 pbr_map_delete_common(pbrms);
363}
364
365void pbr_map_delete_vrf(struct pbr_map_sequence *pbrms)
366{
367 pbr_map_delete_common(pbrms);
368}
369
37c606ff
DS
370struct pbr_map_sequence *pbrms_lookup_unique(uint32_t unique, ifindex_t ifindex,
371 struct pbr_map_interface **ppmi)
e5c83d9b
DS
372{
373 struct pbr_map_sequence *pbrms;
374 struct listnode *snode, *inode;
375 struct pbr_map_interface *pmi;
376 struct pbr_map *pbrm;
377
378 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
379 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi)) {
380 if (pmi->ifp->ifindex != ifindex)
381 continue;
382
37c606ff
DS
383 if (ppmi)
384 *ppmi = pmi;
385
e5c83d9b
DS
386 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, snode,
387 pbrms)) {
388 DEBUGD(&pbr_dbg_map, "%s: Comparing %u to %u",
389 __PRETTY_FUNCTION__, pbrms->unique,
390 unique);
391 if (pbrms->unique == unique)
392 return pbrms;
393 }
394 }
395 }
396
397 return NULL;
398}
399
b13e5ad6
DS
400static void pbr_map_add_interfaces(struct pbr_map *pbrm)
401{
402 struct interface *ifp;
403 struct pbr_interface *pbr_ifp;
404 struct vrf *vrf;
405
406 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
407 FOR_ALL_INTERFACES (vrf, ifp) {
408 if (ifp->info) {
409 pbr_ifp = ifp->info;
410 if (strcmp(pbrm->name, pbr_ifp->mapname) == 0)
411 pbr_map_add_interface(pbrm, ifp);
412 }
413 }
414 }
415}
416
d3765386 417struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno)
e5c83d9b
DS
418{
419 struct pbr_map *pbrm;
420 struct pbr_map_sequence *pbrms;
421 struct listnode *node;
e5c83d9b
DS
422
423 pbrm = pbrm_find(name);
424 if (!pbrm) {
425 pbrm = XCALLOC(MTYPE_PBR_MAP, sizeof(*pbrm));
6612590d 426 snprintf(pbrm->name, sizeof(pbrm->name), "%s", name);
e5c83d9b
DS
427
428 pbrm->seqnumbers = list_new();
429 pbrm->seqnumbers->cmp =
430 (int (*)(void *, void *))pbr_map_sequence_compare;
431 pbrm->seqnumbers->del =
432 (void (*)(void *))pbr_map_sequence_delete;
433
434 pbrm->incoming = list_new();
435 pbrm->incoming->cmp =
436 (int (*)(void *, void *))pbr_map_interface_compare;
437 pbrm->incoming->del =
438 (void (*)(void *))pbr_map_interface_list_delete;
439
440 RB_INSERT(pbr_map_entry_head, &pbr_maps, pbrm);
441
37c606ff 442 bf_init(pbrm->ifi_bitfield, 64);
b13e5ad6
DS
443 pbr_map_add_interfaces(pbrm);
444 }
e5c83d9b
DS
445
446 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
447 if (pbrms->seqno == seqno)
448 break;
449
450 }
451
452 if (!pbrms) {
453 pbrms = XCALLOC(MTYPE_PBR_MAP_SEQNO, sizeof(*pbrms));
454 pbrms->unique = pbr_map_sequence_unique++;
455 pbrms->seqno = seqno;
456 pbrms->ruleno = pbr_nht_get_next_rule(seqno);
457 pbrms->parent = pbrm;
458 pbrms->reason =
95a9fe02 459 PBR_MAP_INVALID_EMPTY |
e5c83d9b 460 PBR_MAP_INVALID_NO_NEXTHOPS;
be3b67b5 461 pbrms->vrf_name[0] = '\0';
e5c83d9b
DS
462
463 QOBJ_REG(pbrms, pbr_map_sequence);
464 listnode_add_sort(pbrm->seqnumbers, pbrms);
e5c83d9b
DS
465 }
466
e5c83d9b
DS
467 return pbrms;
468}
469
470static void
471pbr_map_sequence_check_nexthops_valid(struct pbr_map_sequence *pbrms)
472{
be3b67b5
SW
473 /* Check if any are present first */
474 if (!pbrms->vrf_unchanged && !pbrms->vrf_lookup && !pbrms->nhg
475 && !pbrms->nhgrp_name) {
476 pbrms->reason |= PBR_MAP_INVALID_NO_NEXTHOPS;
477 return;
478 }
479
480 /*
481 * Check validness of vrf.
482 */
483
484 /* This one can be considered always valid */
485 if (pbrms->vrf_unchanged)
486 pbrms->nhs_installed = true;
487
488 if (pbrms->vrf_lookup) {
489 struct pbr_vrf *pbr_vrf =
490 pbr_vrf_lookup_by_name(pbrms->vrf_name);
491
492 if (pbr_vrf && pbr_vrf_is_valid(pbr_vrf))
493 pbrms->nhs_installed = true;
494 else
495 pbrms->reason |= PBR_MAP_INVALID_VRF;
496 }
497
e5c83d9b
DS
498 /*
499 * Check validness of the nexthop or nexthop-group
500 */
e5c83d9b 501
be3b67b5 502 /* Only nexthop or nexthop group allowed */
e5c83d9b
DS
503 if (pbrms->nhg && pbrms->nhgrp_name)
504 pbrms->reason |= PBR_MAP_INVALID_BOTH_NHANDGRP;
505
506 if (pbrms->nhg &&
507 !pbr_nht_nexthop_group_valid(pbrms->internal_nhg_name))
508 pbrms->reason |= PBR_MAP_INVALID_NEXTHOP;
509
510 if (pbrms->nhgrp_name) {
511 if (!pbr_nht_nexthop_group_valid(pbrms->nhgrp_name))
512 pbrms->reason |= PBR_MAP_INVALID_NEXTHOP_GROUP;
513 else
514 pbrms->nhs_installed = true;
515 }
516}
517
95a9fe02 518static void pbr_map_sequence_check_not_empty(struct pbr_map_sequence *pbrms)
e5c83d9b 519{
95a9fe02
MM
520 if (!pbrms->src && !pbrms->dst && !pbrms->mark)
521 pbrms->reason |= PBR_MAP_INVALID_EMPTY;
e5c83d9b
DS
522}
523
524/*
525 * Checks to see if we think that the pbmrs is valid. If we think
526 * the config is valid return true.
527 */
528static void pbr_map_sequence_check_valid(struct pbr_map_sequence *pbrms)
529{
530 pbr_map_sequence_check_nexthops_valid(pbrms);
531
95a9fe02 532 pbr_map_sequence_check_not_empty(pbrms);
e5c83d9b
DS
533}
534
535static bool pbr_map_check_valid_internal(struct pbr_map *pbrm)
536{
537 struct pbr_map_sequence *pbrms;
538 struct listnode *node;
539
540 pbrm->valid = true;
541 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
542 pbrms->reason = 0;
543 pbr_map_sequence_check_valid(pbrms);
544 /*
545 * A pbr_map_sequence that is invalid causes
546 * the whole shebang to be invalid
547 */
548 if (pbrms->reason != 0)
549 pbrm->valid = false;
550 }
551
552 return pbrm->valid;
553}
554
555/*
556 * For a given PBR-MAP check to see if we think it is a
557 * valid config or not. If so note that it is and return
558 * that we are valid.
559 */
d3765386 560bool pbr_map_check_valid(const char *name)
e5c83d9b
DS
561{
562 struct pbr_map *pbrm;
563
564 pbrm = pbrm_find(name);
565 if (!pbrm) {
566 DEBUGD(&pbr_dbg_map,
567 "%s: Specified PBR-MAP(%s) does not exist?",
568 __PRETTY_FUNCTION__, name);
569 return false;
570 }
571
572 pbr_map_check_valid_internal(pbrm);
573 return pbrm->valid;
574}
575
d3765386 576void pbr_map_schedule_policy_from_nhg(const char *nh_group)
e5c83d9b
DS
577{
578 struct pbr_map_sequence *pbrms;
e5c83d9b
DS
579 struct pbr_map *pbrm;
580 struct listnode *node;
581
582 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
583 DEBUGD(&pbr_dbg_map, "%s: Looking at %s", __PRETTY_FUNCTION__,
584 pbrm->name);
585 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
586 DEBUGD(&pbr_dbg_map, "\tNH Grp name: %s",
2f61710b
DS
587 pbrms->nhgrp_name ?
588 pbrms->nhgrp_name : pbrms->internal_nhg_name);
e5c83d9b
DS
589
590 if (pbrms->nhgrp_name
591 && (strcmp(nh_group, pbrms->nhgrp_name) == 0)) {
592 pbrms->nhs_installed = true;
593
b13e5ad6 594 pbr_map_check(pbrms);
e5c83d9b
DS
595 }
596
597 if (pbrms->nhg
598 && (strcmp(nh_group, pbrms->internal_nhg_name)
599 == 0)) {
600 pbrms->nhs_installed = true;
601
b13e5ad6 602 pbr_map_check(pbrms);
e5c83d9b
DS
603 }
604 }
605 }
606}
607
d3765386 608void pbr_map_policy_install(const char *name)
e5c83d9b
DS
609{
610 struct pbr_map_sequence *pbrms;
611 struct pbr_map *pbrm;
b13e5ad6
DS
612 struct listnode *node, *inode;
613 struct pbr_map_interface *pmi;
e5c83d9b
DS
614
615 DEBUGD(&pbr_dbg_map, "%s: for %s", __PRETTY_FUNCTION__, name);
616 pbrm = pbrm_find(name);
617 if (!pbrm)
618 return;
619
e5c83d9b
DS
620 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
621 DEBUGD(&pbr_dbg_map,
622 "%s: Looking at what to install %s(%u) %d %d",
623 __PRETTY_FUNCTION__, name, pbrms->seqno, pbrm->valid,
624 pbrms->nhs_installed);
e5c83d9b 625
be3b67b5
SW
626 if (pbrm->valid && pbrms->nhs_installed
627 && pbrm->incoming->count) {
628 DEBUGD(&pbr_dbg_map, "\tInstalling %s %u", pbrm->name,
629 pbrms->seqno);
b13e5ad6 630 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
be3b67b5
SW
631 if (pbr_map_interface_is_valid(pmi))
632 pbr_send_pbr_map(pbrms, pmi, true);
b13e5ad6 633 }
e5c83d9b
DS
634 }
635}
636
b13e5ad6 637void pbr_map_policy_delete(struct pbr_map *pbrm, struct pbr_map_interface *pmi)
e5c83d9b 638{
b13e5ad6
DS
639 struct listnode *node;
640 struct pbr_map_sequence *pbrms;
e5c83d9b 641
e5c83d9b 642
b13e5ad6
DS
643 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
644 pbr_send_pbr_map(pbrms, pmi, false);
645
38e9ccde 646 pmi->delete = true;
e5c83d9b
DS
647}
648
649/*
650 * For a nexthop group specified, see if any of the pbr-maps
651 * are using it and if so, check to see that we are still
652 * valid for usage. If we are valid then schedule the installation/deletion
653 * of the pbr-policy.
654 */
d3765386 655void pbr_map_check_nh_group_change(const char *nh_group)
e5c83d9b
DS
656{
657 struct pbr_map_sequence *pbrms;
658 struct pbr_map *pbrm;
ff9799c3
DS
659 struct listnode *node, *inode;
660 struct pbr_map_interface *pmi;
e5c83d9b
DS
661 bool found_name;
662
e5c83d9b
DS
663 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
664 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
665 found_name = false;
666 if (pbrms->nhgrp_name)
667 found_name =
668 !strcmp(nh_group, pbrms->nhgrp_name);
669 else if (pbrms->nhg)
670 found_name = !strcmp(nh_group,
671 pbrms->internal_nhg_name);
672
673 if (found_name) {
674 bool original = pbrm->valid;
e5c83d9b
DS
675
676 pbr_map_check_valid_internal(pbrm);
677
ff9799c3 678 if (pbrm->valid && (original != pbrm->valid))
b13e5ad6 679 pbr_map_install(pbrm);
ff9799c3
DS
680
681 if (pbrm->valid == false)
682 for (ALL_LIST_ELEMENTS_RO(
683 pbrm->incoming, inode,
684 pmi))
685 pbr_send_pbr_map(pbrms, pmi,
686 false);
e5c83d9b
DS
687 }
688 }
689 }
690}
691
b13e5ad6 692void pbr_map_check(struct pbr_map_sequence *pbrms)
e5c83d9b 693{
e5c83d9b 694 struct pbr_map *pbrm;
b13e5ad6 695 bool install;
e5c83d9b 696
b13e5ad6
DS
697 pbrm = pbrms->parent;
698 DEBUGD(&pbr_dbg_map, "%s: for %s(%u)", __PRETTY_FUNCTION__,
699 pbrm->name, pbrms->seqno);
700 if (pbr_map_check_valid(pbrm->name))
2f61710b 701 DEBUGD(&pbr_dbg_map, "We are totally valid %s",
b13e5ad6 702 pbrm->name);
e5c83d9b 703
b13e5ad6
DS
704 if (pbrms->reason == PBR_MAP_VALID_SEQUENCE_NUMBER) {
705 install = true;
e5c83d9b 706 DEBUGD(&pbr_dbg_map, "%s: Installing %s(%u) reason: %" PRIu64,
b13e5ad6
DS
707 __PRETTY_FUNCTION__, pbrm->name, pbrms->seqno,
708 pbrms->reason);
e5c83d9b 709 DEBUGD(&pbr_dbg_map,
b13e5ad6
DS
710 "\tSending PBR_MAP_POLICY_INSTALL event");
711 } else {
712 install = false;
e5c83d9b 713 DEBUGD(&pbr_dbg_map,
b13e5ad6
DS
714 "%s: Removing %s(%u) reason: %" PRIu64,
715 __PRETTY_FUNCTION__, pbrm->name,
716 pbrms->seqno, pbrms->reason);
e5c83d9b
DS
717 }
718
be3b67b5
SW
719 if (install)
720 pbr_map_pbrms_install(pbrms);
721 else
722 pbr_map_pbrms_uninstall(pbrms);
e5c83d9b
DS
723}
724
b13e5ad6 725void pbr_map_install(struct pbr_map *pbrm)
e5c83d9b 726{
b13e5ad6 727 struct pbr_map_sequence *pbrms;
be3b67b5 728 struct listnode *node;
e5c83d9b 729
b13e5ad6 730 if (!pbrm->incoming->count)
e5c83d9b 731 return;
e5c83d9b 732
b13e5ad6 733 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
be3b67b5 734 pbr_map_pbrms_install(pbrms);
e5c83d9b
DS
735}
736
d3765386 737void pbr_map_init(void)
e5c83d9b
DS
738{
739 RB_INIT(pbr_map_entry_head, &pbr_maps);
740
741 pbr_map_sequence_unique = 1;
742}