3 * Copyright (C) 2018 Cumulus Networks, Inc.
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
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.
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
28 #include "nexthop_group.h"
35 #include "pbr_zebra.h"
36 #include "pbr_memory.h"
37 #include "pbr_debug.h"
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")
44 static uint32_t pbr_map_sequence_unique
;
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
);
50 RB_GENERATE(pbr_map_entry_head
, pbr_map
, pbr_map_entry
, pbr_map_compare
)
52 struct pbr_map_entry_head pbr_maps
= RB_INITIALIZER(&pbr_maps
);
54 DEFINE_QOBJ_TYPE(pbr_map_sequence
)
56 static inline int pbr_map_compare(const struct pbr_map
*pbrmap1
,
57 const struct pbr_map
*pbrmap2
)
59 return strcmp(pbrmap1
->name
, pbrmap2
->name
);
62 static int pbr_map_sequence_compare(const struct pbr_map_sequence
*pbrms1
,
63 const struct pbr_map_sequence
*pbrms2
)
65 if (pbrms1
->seqno
== pbrms2
->seqno
)
68 if (pbrms1
->seqno
< pbrms2
->seqno
)
74 static void pbr_map_sequence_delete(struct pbr_map_sequence
*pbrms
)
76 XFREE(MTYPE_TMP
, pbrms
->internal_nhg_name
);
79 XFREE(MTYPE_PBR_MAP_SEQNO
, pbrms
);
82 static int pbr_map_interface_compare(const struct pbr_map_interface
*pmi1
,
83 const struct pbr_map_interface
*pmi2
)
85 return strcmp(pmi1
->ifp
->name
, pmi2
->ifp
->name
);
88 static void pbr_map_interface_list_delete(struct pbr_map_interface
*pmi
)
90 struct pbr_map_interface
*pmi_int
;
91 struct listnode
*node
, *nnode
;
94 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
95 for (ALL_LIST_ELEMENTS(pbrm
->incoming
, node
, nnode
, pmi_int
)) {
97 pbr_map_policy_delete(pbrm
, pmi
);
104 static bool pbrms_is_installed(const struct pbr_map_sequence
*pbrms
,
105 const struct pbr_map_interface
*pmi
)
107 uint64_t is_installed
= (uint64_t)1 << pmi
->install_bit
;
109 is_installed
&= pbrms
->installed
;
117 /* If any sequence is installed on the interface, assume installed */
119 pbr_map_interface_is_installed(const struct pbr_map
*pbrm
,
120 const struct pbr_map_interface
*check_pmi
)
123 struct pbr_map_sequence
*pbrms
;
124 struct pbr_map_interface
*pmi
;
125 struct listnode
*node
, *inode
;
127 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
))
128 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, inode
, pmi
))
129 if (pmi
== check_pmi
&& pbrms_is_installed(pbrms
, pmi
))
135 static bool pbr_map_interface_is_valid(const struct pbr_map_interface
*pmi
)
137 /* Don't install rules without a real ifindex on the incoming interface.
139 * This can happen when we have config for an interface that does not
140 * exist or when an interface is changing vrfs.
142 if (pmi
->ifp
&& pmi
->ifp
->ifindex
!= IFINDEX_INTERNAL
)
148 static void pbr_map_pbrms_update_common(struct pbr_map_sequence
*pbrms
,
149 bool install
, bool changed
)
151 struct pbr_map
*pbrm
;
152 struct listnode
*node
;
153 struct pbr_map_interface
*pmi
;
155 pbrm
= pbrms
->parent
;
157 if (pbrms
->nhs_installed
&& pbrm
->incoming
->count
) {
158 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, node
, pmi
)) {
162 if (install
&& !pbr_map_interface_is_valid(pmi
))
165 pbr_send_pbr_map(pbrms
, pmi
, install
, changed
);
170 static void pbr_map_pbrms_install(struct pbr_map_sequence
*pbrms
, bool changed
)
172 pbr_map_pbrms_update_common(pbrms
, true, changed
);
175 static void pbr_map_pbrms_uninstall(struct pbr_map_sequence
*pbrms
)
177 pbr_map_pbrms_update_common(pbrms
, false, false);
180 static const char *const pbr_map_reason_str
[] = {
181 "Invalid NH-group", "Invalid NH", "No Nexthops",
182 "Both NH and NH-Group", "Invalid Src or Dst", "Invalid VRF",
186 void pbr_map_reason_string(unsigned int reason
, char *buf
, int size
)
194 for (bit
= 0; bit
< array_size(pbr_map_reason_str
); bit
++) {
195 if ((reason
& (1 << bit
)) && (len
< size
)) {
196 len
+= snprintf((buf
+ len
), (size
- len
), "%s%s",
197 (len
> 0) ? ", " : "",
198 pbr_map_reason_str
[bit
]);
203 void pbr_map_final_interface_deletion(struct pbr_map
*pbrm
,
204 struct pbr_map_interface
*pmi
)
206 if (pmi
->delete && !pbr_map_interface_is_installed(pbrm
, pmi
)) {
207 listnode_delete(pbrm
->incoming
, pmi
);
210 bf_release_index(pbrm
->ifi_bitfield
, pmi
->install_bit
);
211 XFREE(MTYPE_PBR_MAP_INTERFACE
, pmi
);
215 void pbr_map_interface_delete(struct pbr_map
*pbrm
, struct interface
*ifp_del
)
218 struct listnode
*node
;
219 struct pbr_map_interface
*pmi
;
221 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, node
, pmi
)) {
222 if (ifp_del
== pmi
->ifp
)
227 pbr_map_policy_delete(pbrm
, pmi
);
230 void pbr_map_add_interface(struct pbr_map
*pbrm
, struct interface
*ifp_add
)
232 struct listnode
*node
;
233 struct pbr_map_interface
*pmi
;
235 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, node
, pmi
)) {
236 if (ifp_add
== pmi
->ifp
)
240 pmi
= XCALLOC(MTYPE_PBR_MAP_INTERFACE
, sizeof(*pmi
));
243 listnode_add_sort(pbrm
->incoming
, pmi
);
245 bf_assign_index(pbrm
->ifi_bitfield
, pmi
->install_bit
);
246 pbr_map_check_valid(pbrm
->name
);
248 pbr_map_install(pbrm
);
252 pbr_map_policy_interface_update_common(const struct interface
*ifp
,
253 struct pbr_interface
**pbr_ifp
,
254 struct pbr_map
**pbrm
)
257 DEBUGD(&pbr_dbg_map
, "%s: %s has no pbr_interface info",
258 __func__
, ifp
->name
);
262 *pbr_ifp
= ifp
->info
;
264 *pbrm
= pbrm_find((*pbr_ifp
)->mapname
);
267 DEBUGD(&pbr_dbg_map
, "%s: applied PBR-MAP(%s) does not exist?",
268 __func__
, (*pbr_ifp
)->mapname
);
275 void pbr_map_policy_interface_update(const struct interface
*ifp
, bool state_up
)
277 struct pbr_interface
*pbr_ifp
;
278 struct pbr_map_sequence
*pbrms
;
279 struct pbr_map
*pbrm
;
280 struct listnode
*node
, *inode
;
281 struct pbr_map_interface
*pmi
;
283 if (pbr_map_policy_interface_update_common(ifp
, &pbr_ifp
, &pbrm
))
286 DEBUGD(&pbr_dbg_map
, "%s: %s %s rules on interface %s", __func__
,
287 pbr_ifp
->mapname
, (state_up
? "installing" : "removing"),
291 * Walk the list and install/remove maps on the interface.
293 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
))
294 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, inode
, pmi
))
295 if (pmi
->ifp
== ifp
&& pbr_map_interface_is_valid(pmi
))
296 pbr_send_pbr_map(pbrms
, pmi
, state_up
, true);
299 static void pbrms_vrf_update(struct pbr_map_sequence
*pbrms
,
300 const struct pbr_vrf
*pbr_vrf
)
302 const char *vrf_name
= pbr_vrf_name(pbr_vrf
);
304 if (pbrms
->vrf_lookup
305 && (strncmp(vrf_name
, pbrms
->vrf_name
, sizeof(pbrms
->vrf_name
))
307 DEBUGD(&pbr_dbg_map
, " Seq %u uses vrf %s (%u), updating map",
308 pbrms
->seqno
, vrf_name
, pbr_vrf_id(pbr_vrf
));
310 pbr_map_check(pbrms
, false);
314 /* Vrf enabled/disabled */
315 void pbr_map_vrf_update(const struct pbr_vrf
*pbr_vrf
)
317 struct pbr_map
*pbrm
;
318 struct pbr_map_sequence
*pbrms
;
319 struct listnode
*node
;
324 bool enabled
= pbr_vrf_is_enabled(pbr_vrf
);
326 DEBUGD(&pbr_dbg_map
, "%s: %s (%u) %s, updating pbr maps", __func__
,
327 pbr_vrf_name(pbr_vrf
), pbr_vrf_id(pbr_vrf
),
328 enabled
? "enabled" : "disabled");
330 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
331 DEBUGD(&pbr_dbg_map
, "%s: Looking at %s", __func__
, pbrm
->name
);
332 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
))
333 pbrms_vrf_update(pbrms
, pbr_vrf
);
337 void pbr_map_write_interfaces(struct vty
*vty
, struct interface
*ifp
)
339 struct pbr_interface
*pbr_ifp
= ifp
->info
;
342 && strncmp(pbr_ifp
->mapname
, "", sizeof(pbr_ifp
->mapname
)) != 0)
343 vty_out(vty
, " pbr-policy %s\n", pbr_ifp
->mapname
);
346 struct pbr_map
*pbrm_find(const char *name
)
350 strlcpy(pbrm
.name
, name
, sizeof(pbrm
.name
));
352 return RB_FIND(pbr_map_entry_head
, &pbr_maps
, &pbrm
);
355 extern void pbr_map_delete(struct pbr_map_sequence
*pbrms
)
357 struct pbr_map
*pbrm
;
358 struct listnode
*inode
;
359 struct pbr_map_interface
*pmi
;
361 pbrm
= pbrms
->parent
;
363 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, inode
, pmi
))
364 pbr_send_pbr_map(pbrms
, pmi
, false, false);
367 pbr_nht_delete_individual_nexthop(pbrms
);
369 listnode_delete(pbrm
->seqnumbers
, pbrms
);
371 if (pbrm
->seqnumbers
->count
== 0) {
372 RB_REMOVE(pbr_map_entry_head
, &pbr_maps
, pbrm
);
374 bf_free(pbrm
->ifi_bitfield
);
375 XFREE(MTYPE_PBR_MAP
, pbrm
);
379 static void pbr_map_delete_common(struct pbr_map_sequence
*pbrms
)
381 struct pbr_map
*pbrm
= pbrms
->parent
;
383 pbr_map_pbrms_uninstall(pbrms
);
386 pbrms
->nhs_installed
= false;
387 pbrms
->reason
|= PBR_MAP_INVALID_NO_NEXTHOPS
;
388 XFREE(MTYPE_TMP
, pbrms
->nhgrp_name
);
391 void pbr_map_delete_nexthops(struct pbr_map_sequence
*pbrms
)
393 pbr_map_delete_common(pbrms
);
396 void pbr_map_delete_vrf(struct pbr_map_sequence
*pbrms
)
398 pbr_map_delete_common(pbrms
);
401 struct pbr_map_sequence
*pbrms_lookup_unique(uint32_t unique
, char *ifname
,
402 struct pbr_map_interface
**ppmi
)
404 struct pbr_map_sequence
*pbrms
;
405 struct listnode
*snode
, *inode
;
406 struct pbr_map_interface
*pmi
;
407 struct pbr_map
*pbrm
;
409 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
410 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, inode
, pmi
)) {
411 if (strncmp(pmi
->ifp
->name
, ifname
, INTERFACE_NAMSIZ
)
418 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, snode
,
420 DEBUGD(&pbr_dbg_map
, "%s: Comparing %u to %u",
421 __func__
, pbrms
->unique
, unique
);
422 if (pbrms
->unique
== unique
)
431 static void pbr_map_add_interfaces(struct pbr_map
*pbrm
)
433 struct interface
*ifp
;
434 struct pbr_interface
*pbr_ifp
;
437 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
438 FOR_ALL_INTERFACES (vrf
, ifp
) {
441 if (strcmp(pbrm
->name
, pbr_ifp
->mapname
) == 0)
442 pbr_map_add_interface(pbrm
, ifp
);
448 /* Decodes a standardized DSCP into its representative value */
449 uint8_t pbr_map_decode_dscp_enum(const char *name
)
451 /* Standard Differentiated Services Field Codepoints */
452 if (!strcmp(name
, "cs0"))
454 if (!strcmp(name
, "cs1"))
456 if (!strcmp(name
, "cs2"))
458 if (!strcmp(name
, "cs3"))
460 if (!strcmp(name
, "cs4"))
462 if (!strcmp(name
, "cs5"))
464 if (!strcmp(name
, "cs6"))
466 if (!strcmp(name
, "cs7"))
468 if (!strcmp(name
, "af11"))
470 if (!strcmp(name
, "af12"))
472 if (!strcmp(name
, "af13"))
474 if (!strcmp(name
, "af21"))
476 if (!strcmp(name
, "af22"))
478 if (!strcmp(name
, "af23"))
480 if (!strcmp(name
, "af31"))
482 if (!strcmp(name
, "af32"))
484 if (!strcmp(name
, "af33"))
486 if (!strcmp(name
, "af41"))
488 if (!strcmp(name
, "af42"))
490 if (!strcmp(name
, "af43"))
492 if (!strcmp(name
, "ef"))
494 if (!strcmp(name
, "voice-admit"))
497 /* No match? Error out */
501 struct pbr_map_sequence
*pbrms_get(const char *name
, uint32_t seqno
)
503 struct pbr_map
*pbrm
;
504 struct pbr_map_sequence
*pbrms
;
505 struct listnode
*node
;
507 pbrm
= pbrm_find(name
);
509 pbrm
= XCALLOC(MTYPE_PBR_MAP
, sizeof(*pbrm
));
510 snprintf(pbrm
->name
, sizeof(pbrm
->name
), "%s", name
);
512 pbrm
->seqnumbers
= list_new();
513 pbrm
->seqnumbers
->cmp
=
514 (int (*)(void *, void *))pbr_map_sequence_compare
;
515 pbrm
->seqnumbers
->del
=
516 (void (*)(void *))pbr_map_sequence_delete
;
518 pbrm
->incoming
= list_new();
519 pbrm
->incoming
->cmp
=
520 (int (*)(void *, void *))pbr_map_interface_compare
;
521 pbrm
->incoming
->del
=
522 (void (*)(void *))pbr_map_interface_list_delete
;
524 RB_INSERT(pbr_map_entry_head
, &pbr_maps
, pbrm
);
526 bf_init(pbrm
->ifi_bitfield
, 64);
527 pbr_map_add_interfaces(pbrm
);
530 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
531 if (pbrms
->seqno
== seqno
)
537 pbrms
= XCALLOC(MTYPE_PBR_MAP_SEQNO
, sizeof(*pbrms
));
538 pbrms
->unique
= pbr_map_sequence_unique
++;
539 pbrms
->seqno
= seqno
;
540 pbrms
->ruleno
= pbr_nht_get_next_rule(seqno
);
541 pbrms
->parent
= pbrm
;
543 PBR_MAP_INVALID_EMPTY
|
544 PBR_MAP_INVALID_NO_NEXTHOPS
;
545 pbrms
->vrf_name
[0] = '\0';
547 QOBJ_REG(pbrms
, pbr_map_sequence
);
548 listnode_add_sort(pbrm
->seqnumbers
, pbrms
);
555 pbr_map_sequence_check_nexthops_valid(struct pbr_map_sequence
*pbrms
)
557 /* Check if any are present first */
558 if (!pbrms
->vrf_unchanged
&& !pbrms
->vrf_lookup
&& !pbrms
->nhg
559 && !pbrms
->nhgrp_name
) {
560 pbrms
->reason
|= PBR_MAP_INVALID_NO_NEXTHOPS
;
565 * Check validness of vrf.
568 /* This one can be considered always valid */
569 if (pbrms
->vrf_unchanged
)
570 pbrms
->nhs_installed
= true;
572 if (pbrms
->vrf_lookup
) {
573 struct pbr_vrf
*pbr_vrf
=
574 pbr_vrf_lookup_by_name(pbrms
->vrf_name
);
576 if (pbr_vrf
&& pbr_vrf_is_valid(pbr_vrf
))
577 pbrms
->nhs_installed
= true;
579 pbrms
->reason
|= PBR_MAP_INVALID_VRF
;
583 * Check validness of the nexthop or nexthop-group
586 /* Only nexthop or nexthop group allowed */
587 if (pbrms
->nhg
&& pbrms
->nhgrp_name
)
588 pbrms
->reason
|= PBR_MAP_INVALID_BOTH_NHANDGRP
;
591 !pbr_nht_nexthop_group_valid(pbrms
->internal_nhg_name
))
592 pbrms
->reason
|= PBR_MAP_INVALID_NEXTHOP
;
594 if (pbrms
->nhgrp_name
) {
595 if (!pbr_nht_nexthop_group_valid(pbrms
->nhgrp_name
))
596 pbrms
->reason
|= PBR_MAP_INVALID_NEXTHOP_GROUP
;
598 pbrms
->nhs_installed
= true;
602 static void pbr_map_sequence_check_not_empty(struct pbr_map_sequence
*pbrms
)
604 if (!pbrms
->src
&& !pbrms
->dst
&& !pbrms
->mark
&& !pbrms
->dsfield
)
605 pbrms
->reason
|= PBR_MAP_INVALID_EMPTY
;
609 * Checks to see if we think that the pbmrs is valid. If we think
610 * the config is valid return true.
612 static void pbr_map_sequence_check_valid(struct pbr_map_sequence
*pbrms
)
614 pbr_map_sequence_check_nexthops_valid(pbrms
);
616 pbr_map_sequence_check_not_empty(pbrms
);
619 static bool pbr_map_check_valid_internal(struct pbr_map
*pbrm
)
621 struct pbr_map_sequence
*pbrms
;
622 struct listnode
*node
;
625 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
627 pbr_map_sequence_check_valid(pbrms
);
629 * A pbr_map_sequence that is invalid causes
630 * the whole shebang to be invalid
632 if (pbrms
->reason
!= 0)
640 * For a given PBR-MAP check to see if we think it is a
641 * valid config or not. If so note that it is and return
644 bool pbr_map_check_valid(const char *name
)
646 struct pbr_map
*pbrm
;
648 pbrm
= pbrm_find(name
);
651 "%s: Specified PBR-MAP(%s) does not exist?", __func__
,
656 pbr_map_check_valid_internal(pbrm
);
660 void pbr_map_schedule_policy_from_nhg(const char *nh_group
, bool installed
)
662 struct pbr_map_sequence
*pbrms
;
663 struct pbr_map
*pbrm
;
664 struct listnode
*node
;
666 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
667 DEBUGD(&pbr_dbg_map
, "%s: Looking at %s", __func__
, pbrm
->name
);
668 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
669 DEBUGD(&pbr_dbg_map
, " NH Grp name: %s",
671 pbrms
->nhgrp_name
: pbrms
->internal_nhg_name
);
673 if (pbrms
->nhgrp_name
674 && (strcmp(nh_group
, pbrms
->nhgrp_name
) == 0)) {
675 pbrms
->nhs_installed
= installed
;
677 pbr_map_check(pbrms
, false);
681 && (strcmp(nh_group
, pbrms
->internal_nhg_name
)
683 pbrms
->nhs_installed
= installed
;
685 pbr_map_check(pbrms
, false);
691 void pbr_map_policy_install(const char *name
)
693 struct pbr_map_sequence
*pbrms
;
694 struct pbr_map
*pbrm
;
695 struct listnode
*node
, *inode
;
696 struct pbr_map_interface
*pmi
;
698 DEBUGD(&pbr_dbg_map
, "%s: for %s", __func__
, name
);
699 pbrm
= pbrm_find(name
);
703 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
705 "%s: Looking at what to install %s(%u) %d %d", __func__
,
706 name
, pbrms
->seqno
, pbrm
->valid
, pbrms
->nhs_installed
);
708 if (pbrm
->valid
&& pbrms
->nhs_installed
709 && pbrm
->incoming
->count
) {
710 DEBUGD(&pbr_dbg_map
, " Installing %s %u", pbrm
->name
,
712 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, inode
, pmi
))
713 if (pbr_map_interface_is_valid(pmi
))
714 pbr_send_pbr_map(pbrms
, pmi
, true,
720 void pbr_map_policy_delete(struct pbr_map
*pbrm
, struct pbr_map_interface
*pmi
)
722 struct listnode
*node
;
723 struct pbr_map_sequence
*pbrms
;
727 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
))
728 if (pbr_send_pbr_map(pbrms
, pmi
, false, true))
729 sent
= true; /* rule removal sent to zebra */
734 * If we actually sent something for deletion, wait on zapi callback
735 * before clearing data.
740 pbr_map_final_interface_deletion(pbrm
, pmi
);
744 * For a nexthop group specified, see if any of the pbr-maps
745 * are using it and if so, check to see that we are still
746 * valid for usage. If we are valid then schedule the installation/deletion
749 void pbr_map_check_nh_group_change(const char *nh_group
)
751 struct pbr_map_sequence
*pbrms
;
752 struct pbr_map
*pbrm
;
753 struct listnode
*node
, *inode
;
754 struct pbr_map_interface
*pmi
;
757 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
758 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
760 if (pbrms
->nhgrp_name
)
762 !strcmp(nh_group
, pbrms
->nhgrp_name
);
764 found_name
= !strcmp(nh_group
,
765 pbrms
->internal_nhg_name
);
768 bool original
= pbrm
->valid
;
770 pbr_map_check_valid_internal(pbrm
);
772 if (pbrm
->valid
&& (original
!= pbrm
->valid
))
773 pbr_map_install(pbrm
);
775 if (pbrm
->valid
== false)
776 for (ALL_LIST_ELEMENTS_RO(
777 pbrm
->incoming
, inode
,
779 pbr_send_pbr_map(pbrms
, pmi
,
786 void pbr_map_check_vrf_nh_group_change(const char *nh_group
,
787 struct pbr_vrf
*pbr_vrf
,
790 struct pbr_map
*pbrm
;
791 struct pbr_map_sequence
*pbrms
;
792 struct listnode
*node
;
795 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
796 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
797 if (pbrms
->nhgrp_name
)
800 if (pbrms
->nhg
== NULL
)
803 if (strcmp(nh_group
, pbrms
->internal_nhg_name
))
806 if (pbrms
->nhg
->nexthop
== NULL
)
809 if (pbrms
->nhg
->nexthop
->vrf_id
!= old_vrf_id
)
812 pbrms
->nhg
->nexthop
->vrf_id
= pbr_vrf_id(pbr_vrf
);
817 void pbr_map_check_interface_nh_group_change(const char *nh_group
,
818 struct interface
*ifp
,
819 ifindex_t oldifindex
)
821 struct pbr_map
*pbrm
;
822 struct pbr_map_sequence
*pbrms
;
823 struct listnode
*node
;
825 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
826 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
827 if (pbrms
->nhgrp_name
)
830 if (pbrms
->nhg
== NULL
)
833 if (strcmp(nh_group
, pbrms
->internal_nhg_name
))
836 if (pbrms
->nhg
->nexthop
== NULL
)
839 if (pbrms
->nhg
->nexthop
->ifindex
!= oldifindex
)
842 pbrms
->nhg
->nexthop
->ifindex
= ifp
->ifindex
;
847 void pbr_map_check(struct pbr_map_sequence
*pbrms
, bool changed
)
849 struct pbr_map
*pbrm
;
852 pbrm
= pbrms
->parent
;
853 DEBUGD(&pbr_dbg_map
, "%s: for %s(%u)", __func__
, pbrm
->name
,
855 if (pbr_map_check_valid(pbrm
->name
))
856 DEBUGD(&pbr_dbg_map
, "We are totally valid %s",
859 if (pbrms
->reason
== PBR_MAP_VALID_SEQUENCE_NUMBER
) {
861 DEBUGD(&pbr_dbg_map
, "%s: Installing %s(%u) reason: %" PRIu64
,
862 __func__
, pbrm
->name
, pbrms
->seqno
, pbrms
->reason
);
864 " Sending PBR_MAP_POLICY_INSTALL event");
867 DEBUGD(&pbr_dbg_map
, "%s: Removing %s(%u) reason: %" PRIu64
,
868 __func__
, pbrm
->name
, pbrms
->seqno
, pbrms
->reason
);
872 pbr_map_pbrms_install(pbrms
, changed
);
874 pbr_map_pbrms_uninstall(pbrms
);
877 void pbr_map_install(struct pbr_map
*pbrm
)
879 struct pbr_map_sequence
*pbrms
;
880 struct listnode
*node
;
882 if (!pbrm
->incoming
->count
)
885 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
))
886 pbr_map_pbrms_install(pbrms
, false);
889 void pbr_map_init(void)
891 RB_INIT(pbr_map_entry_head
, &pbr_maps
);
893 pbr_map_sequence_unique
= 1;