]> git.proxmox.com Git - mirror_frr.git/blob - pbrd/pbr_map.c
Merge pull request #5653 from slankdev/slankdev-bgpd-support-prefix-sid-srv6-l3vpn
[mirror_frr.git] / pbrd / pbr_map.c
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"
35 #include "pbr_zebra.h"
36 #include "pbr_memory.h"
37 #include "pbr_debug.h"
38 #include "pbr_vrf.h"
39
40 DEFINE_MTYPE_STATIC(PBRD, PBR_MAP, "PBR Map")
41 DEFINE_MTYPE_STATIC(PBRD, PBR_MAP_SEQNO, "PBR Map Sequence")
42 DEFINE_MTYPE_STATIC(PBRD, PBR_MAP_INTERFACE, "PBR Map Interface")
43
44 static uint32_t pbr_map_sequence_unique;
45
46 static bool pbr_map_check_valid_internal(struct pbr_map *pbrm);
47 static inline int pbr_map_compare(const struct pbr_map *pbrmap1,
48 const struct pbr_map *pbrmap2);
49
50 RB_GENERATE(pbr_map_entry_head, pbr_map, pbr_map_entry, pbr_map_compare)
51
52 struct pbr_map_entry_head pbr_maps = RB_INITIALIZER(&pbr_maps);
53
54 DEFINE_QOBJ_TYPE(pbr_map_sequence)
55
56 static inline int pbr_map_compare(const struct pbr_map *pbrmap1,
57 const struct pbr_map *pbrmap2)
58 {
59 return strcmp(pbrmap1->name, pbrmap2->name);
60 }
61
62 static 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
74 static void pbr_map_sequence_delete(struct pbr_map_sequence *pbrms)
75 {
76 XFREE(MTYPE_TMP, pbrms->internal_nhg_name);
77
78 XFREE(MTYPE_PBR_MAP_SEQNO, pbrms);
79 }
80
81 static 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
87 static void pbr_map_interface_list_delete(struct pbr_map_interface *pmi)
88 {
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 }
101 }
102
103 static 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 */
117 static bool
118 pbr_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
134 static 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
147 static void pbr_map_pbrms_update_common(struct pbr_map_sequence *pbrms,
148 bool install)
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
164 pbr_send_pbr_map(pbrms, pmi, install);
165 }
166 }
167 }
168
169 static void pbr_map_pbrms_install(struct pbr_map_sequence *pbrms)
170 {
171 pbr_map_pbrms_update_common(pbrms, true);
172 }
173
174 static void pbr_map_pbrms_uninstall(struct pbr_map_sequence *pbrms)
175 {
176 pbr_map_pbrms_update_common(pbrms, false);
177 }
178
179 static const char *const pbr_map_reason_str[] = {
180 "Invalid NH-group", "Invalid NH", "No Nexthops",
181 "Both NH and NH-Group", "Invalid Src or Dst", "Invalid VRF",
182 "Deleting Sequence",
183 };
184
185 void 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
202 void pbr_map_final_interface_deletion(struct pbr_map *pbrm,
203 struct pbr_map_interface *pmi)
204 {
205 if (pmi->delete == true && !pbr_map_interface_is_installed(pbrm, pmi)) {
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 }
213
214 void pbr_map_interface_delete(struct pbr_map *pbrm, struct interface *ifp_del)
215 {
216
217 struct listnode *node;
218 struct pbr_map_interface *pmi;
219
220 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) {
221 if (ifp_del == pmi->ifp)
222 break;
223 }
224
225 if (pmi)
226 pbr_map_policy_delete(pbrm, pmi);
227 }
228
229 void pbr_map_add_interface(struct pbr_map *pbrm, struct interface *ifp_add)
230 {
231 struct listnode *node;
232 struct pbr_map_interface *pmi;
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
244 bf_assign_index(pbrm->ifi_bitfield, pmi->install_bit);
245 pbr_map_check_valid(pbrm->name);
246 if (pbrm->valid)
247 pbr_map_install(pbrm);
248 }
249
250 static int
251 pbr_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
274 void 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))
295 pbr_send_pbr_map(pbrms, pmi, state_up);
296 }
297
298 static 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
309 pbr_map_check(pbrms);
310 }
311 }
312
313 /* Vrf enabled/disabled */
314 void 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) {
330 DEBUGD(&pbr_dbg_map, "%s: Looking at %s", __PRETTY_FUNCTION__,
331 pbrm->name);
332 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
333 pbrms_vrf_update(pbrms, pbr_vrf);
334 }
335 }
336
337 void pbr_map_write_interfaces(struct vty *vty, struct interface *ifp)
338 {
339 struct pbr_interface *pbr_ifp = ifp->info;
340
341 if (pbr_ifp
342 && strncmp(pbr_ifp->mapname, "", sizeof(pbr_ifp->mapname)) != 0)
343 vty_out(vty, " pbr-policy %s\n", pbr_ifp->mapname);
344 }
345
346 struct pbr_map *pbrm_find(const char *name)
347 {
348 struct pbr_map pbrm;
349
350 strlcpy(pbrm.name, name, sizeof(pbrm.name));
351
352 return RB_FIND(pbr_map_entry_head, &pbr_maps, &pbrm);
353 }
354
355 extern void pbr_map_delete(struct pbr_map_sequence *pbrms)
356 {
357 struct pbr_map *pbrm;
358 struct listnode *inode;
359 struct pbr_map_interface *pmi;
360
361 pbrm = pbrms->parent;
362
363 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
364 pbr_send_pbr_map(pbrms, pmi, false);
365
366 if (pbrms->nhg)
367 pbr_nht_delete_individual_nexthop(pbrms);
368
369 listnode_delete(pbrm->seqnumbers, pbrms);
370
371 if (pbrm->seqnumbers->count == 0) {
372 RB_REMOVE(pbr_map_entry_head, &pbr_maps, pbrm);
373
374 bf_free(pbrm->ifi_bitfield);
375 XFREE(MTYPE_PBR_MAP, pbrm);
376 }
377 }
378
379 static void pbr_map_delete_common(struct pbr_map_sequence *pbrms)
380 {
381 struct pbr_map *pbrm = pbrms->parent;
382
383 pbr_map_pbrms_uninstall(pbrms);
384
385 pbrm->valid = false;
386 pbrms->nhs_installed = false;
387 pbrms->reason |= PBR_MAP_INVALID_NO_NEXTHOPS;
388 pbrms->nhgrp_name = NULL;
389 }
390
391 void pbr_map_delete_nexthops(struct pbr_map_sequence *pbrms)
392 {
393 pbr_map_delete_common(pbrms);
394 }
395
396 void pbr_map_delete_vrf(struct pbr_map_sequence *pbrms)
397 {
398 pbr_map_delete_common(pbrms);
399 }
400
401 struct pbr_map_sequence *pbrms_lookup_unique(uint32_t unique, ifindex_t ifindex,
402 struct pbr_map_interface **ppmi)
403 {
404 struct pbr_map_sequence *pbrms;
405 struct listnode *snode, *inode;
406 struct pbr_map_interface *pmi;
407 struct pbr_map *pbrm;
408
409 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
410 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi)) {
411 if (pmi->ifp->ifindex != ifindex)
412 continue;
413
414 if (ppmi)
415 *ppmi = pmi;
416
417 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, snode,
418 pbrms)) {
419 DEBUGD(&pbr_dbg_map, "%s: Comparing %u to %u",
420 __PRETTY_FUNCTION__, pbrms->unique,
421 unique);
422 if (pbrms->unique == unique)
423 return pbrms;
424 }
425 }
426 }
427
428 return NULL;
429 }
430
431 static void pbr_map_add_interfaces(struct pbr_map *pbrm)
432 {
433 struct interface *ifp;
434 struct pbr_interface *pbr_ifp;
435 struct vrf *vrf;
436
437 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
438 FOR_ALL_INTERFACES (vrf, ifp) {
439 if (ifp->info) {
440 pbr_ifp = ifp->info;
441 if (strcmp(pbrm->name, pbr_ifp->mapname) == 0)
442 pbr_map_add_interface(pbrm, ifp);
443 }
444 }
445 }
446 }
447
448 struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno)
449 {
450 struct pbr_map *pbrm;
451 struct pbr_map_sequence *pbrms;
452 struct listnode *node;
453
454 pbrm = pbrm_find(name);
455 if (!pbrm) {
456 pbrm = XCALLOC(MTYPE_PBR_MAP, sizeof(*pbrm));
457 snprintf(pbrm->name, sizeof(pbrm->name), "%s", name);
458
459 pbrm->seqnumbers = list_new();
460 pbrm->seqnumbers->cmp =
461 (int (*)(void *, void *))pbr_map_sequence_compare;
462 pbrm->seqnumbers->del =
463 (void (*)(void *))pbr_map_sequence_delete;
464
465 pbrm->incoming = list_new();
466 pbrm->incoming->cmp =
467 (int (*)(void *, void *))pbr_map_interface_compare;
468 pbrm->incoming->del =
469 (void (*)(void *))pbr_map_interface_list_delete;
470
471 RB_INSERT(pbr_map_entry_head, &pbr_maps, pbrm);
472
473 bf_init(pbrm->ifi_bitfield, 64);
474 pbr_map_add_interfaces(pbrm);
475 }
476
477 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
478 if (pbrms->seqno == seqno)
479 break;
480
481 }
482
483 if (!pbrms) {
484 pbrms = XCALLOC(MTYPE_PBR_MAP_SEQNO, sizeof(*pbrms));
485 pbrms->unique = pbr_map_sequence_unique++;
486 pbrms->seqno = seqno;
487 pbrms->ruleno = pbr_nht_get_next_rule(seqno);
488 pbrms->parent = pbrm;
489 pbrms->reason =
490 PBR_MAP_INVALID_EMPTY |
491 PBR_MAP_INVALID_NO_NEXTHOPS;
492 pbrms->vrf_name[0] = '\0';
493
494 QOBJ_REG(pbrms, pbr_map_sequence);
495 listnode_add_sort(pbrm->seqnumbers, pbrms);
496 }
497
498 return pbrms;
499 }
500
501 static void
502 pbr_map_sequence_check_nexthops_valid(struct pbr_map_sequence *pbrms)
503 {
504 /* Check if any are present first */
505 if (!pbrms->vrf_unchanged && !pbrms->vrf_lookup && !pbrms->nhg
506 && !pbrms->nhgrp_name) {
507 pbrms->reason |= PBR_MAP_INVALID_NO_NEXTHOPS;
508 return;
509 }
510
511 /*
512 * Check validness of vrf.
513 */
514
515 /* This one can be considered always valid */
516 if (pbrms->vrf_unchanged)
517 pbrms->nhs_installed = true;
518
519 if (pbrms->vrf_lookup) {
520 struct pbr_vrf *pbr_vrf =
521 pbr_vrf_lookup_by_name(pbrms->vrf_name);
522
523 if (pbr_vrf && pbr_vrf_is_valid(pbr_vrf))
524 pbrms->nhs_installed = true;
525 else
526 pbrms->reason |= PBR_MAP_INVALID_VRF;
527 }
528
529 /*
530 * Check validness of the nexthop or nexthop-group
531 */
532
533 /* Only nexthop or nexthop group allowed */
534 if (pbrms->nhg && pbrms->nhgrp_name)
535 pbrms->reason |= PBR_MAP_INVALID_BOTH_NHANDGRP;
536
537 if (pbrms->nhg &&
538 !pbr_nht_nexthop_group_valid(pbrms->internal_nhg_name))
539 pbrms->reason |= PBR_MAP_INVALID_NEXTHOP;
540
541 if (pbrms->nhgrp_name) {
542 if (!pbr_nht_nexthop_group_valid(pbrms->nhgrp_name))
543 pbrms->reason |= PBR_MAP_INVALID_NEXTHOP_GROUP;
544 else
545 pbrms->nhs_installed = true;
546 }
547 }
548
549 static void pbr_map_sequence_check_not_empty(struct pbr_map_sequence *pbrms)
550 {
551 if (!pbrms->src && !pbrms->dst && !pbrms->mark)
552 pbrms->reason |= PBR_MAP_INVALID_EMPTY;
553 }
554
555 /*
556 * Checks to see if we think that the pbmrs is valid. If we think
557 * the config is valid return true.
558 */
559 static void pbr_map_sequence_check_valid(struct pbr_map_sequence *pbrms)
560 {
561 pbr_map_sequence_check_nexthops_valid(pbrms);
562
563 pbr_map_sequence_check_not_empty(pbrms);
564 }
565
566 static bool pbr_map_check_valid_internal(struct pbr_map *pbrm)
567 {
568 struct pbr_map_sequence *pbrms;
569 struct listnode *node;
570
571 pbrm->valid = true;
572 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
573 pbrms->reason = 0;
574 pbr_map_sequence_check_valid(pbrms);
575 /*
576 * A pbr_map_sequence that is invalid causes
577 * the whole shebang to be invalid
578 */
579 if (pbrms->reason != 0)
580 pbrm->valid = false;
581 }
582
583 return pbrm->valid;
584 }
585
586 /*
587 * For a given PBR-MAP check to see if we think it is a
588 * valid config or not. If so note that it is and return
589 * that we are valid.
590 */
591 bool pbr_map_check_valid(const char *name)
592 {
593 struct pbr_map *pbrm;
594
595 pbrm = pbrm_find(name);
596 if (!pbrm) {
597 DEBUGD(&pbr_dbg_map,
598 "%s: Specified PBR-MAP(%s) does not exist?",
599 __PRETTY_FUNCTION__, name);
600 return false;
601 }
602
603 pbr_map_check_valid_internal(pbrm);
604 return pbrm->valid;
605 }
606
607 void pbr_map_schedule_policy_from_nhg(const char *nh_group)
608 {
609 struct pbr_map_sequence *pbrms;
610 struct pbr_map *pbrm;
611 struct listnode *node;
612
613 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
614 DEBUGD(&pbr_dbg_map, "%s: Looking at %s", __PRETTY_FUNCTION__,
615 pbrm->name);
616 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
617 DEBUGD(&pbr_dbg_map, "\tNH Grp name: %s",
618 pbrms->nhgrp_name ?
619 pbrms->nhgrp_name : pbrms->internal_nhg_name);
620
621 if (pbrms->nhgrp_name
622 && (strcmp(nh_group, pbrms->nhgrp_name) == 0)) {
623 pbrms->nhs_installed = true;
624
625 pbr_map_check(pbrms);
626 }
627
628 if (pbrms->nhg
629 && (strcmp(nh_group, pbrms->internal_nhg_name)
630 == 0)) {
631 pbrms->nhs_installed = true;
632
633 pbr_map_check(pbrms);
634 }
635 }
636 }
637 }
638
639 void pbr_map_policy_install(const char *name)
640 {
641 struct pbr_map_sequence *pbrms;
642 struct pbr_map *pbrm;
643 struct listnode *node, *inode;
644 struct pbr_map_interface *pmi;
645
646 DEBUGD(&pbr_dbg_map, "%s: for %s", __PRETTY_FUNCTION__, name);
647 pbrm = pbrm_find(name);
648 if (!pbrm)
649 return;
650
651 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
652 DEBUGD(&pbr_dbg_map,
653 "%s: Looking at what to install %s(%u) %d %d",
654 __PRETTY_FUNCTION__, name, pbrms->seqno, pbrm->valid,
655 pbrms->nhs_installed);
656
657 if (pbrm->valid && pbrms->nhs_installed
658 && pbrm->incoming->count) {
659 DEBUGD(&pbr_dbg_map, "\tInstalling %s %u", pbrm->name,
660 pbrms->seqno);
661 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
662 if (pbr_map_interface_is_valid(pmi))
663 pbr_send_pbr_map(pbrms, pmi, true);
664 }
665 }
666 }
667
668 void pbr_map_policy_delete(struct pbr_map *pbrm, struct pbr_map_interface *pmi)
669 {
670 struct listnode *node;
671 struct pbr_map_sequence *pbrms;
672
673
674 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
675 pbr_send_pbr_map(pbrms, pmi, false);
676
677 pmi->delete = true;
678 }
679
680 /*
681 * For a nexthop group specified, see if any of the pbr-maps
682 * are using it and if so, check to see that we are still
683 * valid for usage. If we are valid then schedule the installation/deletion
684 * of the pbr-policy.
685 */
686 void pbr_map_check_nh_group_change(const char *nh_group)
687 {
688 struct pbr_map_sequence *pbrms;
689 struct pbr_map *pbrm;
690 struct listnode *node, *inode;
691 struct pbr_map_interface *pmi;
692 bool found_name;
693
694 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
695 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
696 found_name = false;
697 if (pbrms->nhgrp_name)
698 found_name =
699 !strcmp(nh_group, pbrms->nhgrp_name);
700 else if (pbrms->nhg)
701 found_name = !strcmp(nh_group,
702 pbrms->internal_nhg_name);
703
704 if (found_name) {
705 bool original = pbrm->valid;
706
707 pbr_map_check_valid_internal(pbrm);
708
709 if (pbrm->valid && (original != pbrm->valid))
710 pbr_map_install(pbrm);
711
712 if (pbrm->valid == false)
713 for (ALL_LIST_ELEMENTS_RO(
714 pbrm->incoming, inode,
715 pmi))
716 pbr_send_pbr_map(pbrms, pmi,
717 false);
718 }
719 }
720 }
721 }
722
723 void pbr_map_check(struct pbr_map_sequence *pbrms)
724 {
725 struct pbr_map *pbrm;
726 bool install;
727
728 pbrm = pbrms->parent;
729 DEBUGD(&pbr_dbg_map, "%s: for %s(%u)", __PRETTY_FUNCTION__,
730 pbrm->name, pbrms->seqno);
731 if (pbr_map_check_valid(pbrm->name))
732 DEBUGD(&pbr_dbg_map, "We are totally valid %s",
733 pbrm->name);
734
735 if (pbrms->reason == PBR_MAP_VALID_SEQUENCE_NUMBER) {
736 install = true;
737 DEBUGD(&pbr_dbg_map, "%s: Installing %s(%u) reason: %" PRIu64,
738 __PRETTY_FUNCTION__, pbrm->name, pbrms->seqno,
739 pbrms->reason);
740 DEBUGD(&pbr_dbg_map,
741 "\tSending PBR_MAP_POLICY_INSTALL event");
742 } else {
743 install = false;
744 DEBUGD(&pbr_dbg_map,
745 "%s: Removing %s(%u) reason: %" PRIu64,
746 __PRETTY_FUNCTION__, pbrm->name,
747 pbrms->seqno, pbrms->reason);
748 }
749
750 if (install)
751 pbr_map_pbrms_install(pbrms);
752 else
753 pbr_map_pbrms_uninstall(pbrms);
754 }
755
756 void pbr_map_install(struct pbr_map *pbrm)
757 {
758 struct pbr_map_sequence *pbrms;
759 struct listnode *node;
760
761 if (!pbrm->incoming->count)
762 return;
763
764 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
765 pbr_map_pbrms_install(pbrms);
766 }
767
768 void pbr_map_init(void)
769 {
770 RB_INIT(pbr_map_entry_head, &pbr_maps);
771
772 pbr_map_sequence_unique = 1;
773 }