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