1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2018 Cumulus Networks, Inc.
15 #include "nexthop_group.h"
22 #include "pbr_zebra.h"
23 #include "pbr_memory.h"
24 #include "pbr_debug.h"
27 DEFINE_MTYPE_STATIC(PBRD
, PBR_MAP
, "PBR Map");
28 DEFINE_MTYPE_STATIC(PBRD
, PBR_MAP_SEQNO
, "PBR Map Sequence");
29 DEFINE_MTYPE_STATIC(PBRD
, PBR_MAP_INTERFACE
, "PBR Map Interface");
31 static uint32_t pbr_map_sequence_unique
;
33 static bool pbr_map_check_valid_internal(struct pbr_map
*pbrm
);
34 static inline int pbr_map_compare(const struct pbr_map
*pbrmap1
,
35 const struct pbr_map
*pbrmap2
);
37 RB_GENERATE(pbr_map_entry_head
, pbr_map
, pbr_map_entry
, pbr_map_compare
)
39 struct pbr_map_entry_head pbr_maps
= RB_INITIALIZER(&pbr_maps
);
41 DEFINE_QOBJ_TYPE(pbr_map_sequence
);
43 static inline int pbr_map_compare(const struct pbr_map
*pbrmap1
,
44 const struct pbr_map
*pbrmap2
)
46 return strcmp(pbrmap1
->name
, pbrmap2
->name
);
49 static int pbr_map_sequence_compare(const struct pbr_map_sequence
*pbrms1
,
50 const struct pbr_map_sequence
*pbrms2
)
52 if (pbrms1
->seqno
== pbrms2
->seqno
)
55 if (pbrms1
->seqno
< pbrms2
->seqno
)
61 static void pbr_map_sequence_delete(struct pbr_map_sequence
*pbrms
)
63 XFREE(MTYPE_TMP
, pbrms
->internal_nhg_name
);
66 XFREE(MTYPE_PBR_MAP_SEQNO
, pbrms
);
69 static int pbr_map_interface_compare(const struct pbr_map_interface
*pmi1
,
70 const struct pbr_map_interface
*pmi2
)
72 return strcmp(pmi1
->ifp
->name
, pmi2
->ifp
->name
);
75 static void pbr_map_interface_list_delete(struct pbr_map_interface
*pmi
)
77 struct pbr_map_interface
*pmi_int
;
78 struct listnode
*node
, *nnode
;
81 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
82 for (ALL_LIST_ELEMENTS(pbrm
->incoming
, node
, nnode
, pmi_int
)) {
84 pbr_map_policy_delete(pbrm
, pmi
);
91 static bool pbrms_is_installed(const struct pbr_map_sequence
*pbrms
,
92 const struct pbr_map_interface
*pmi
)
94 uint64_t is_installed
= (uint64_t)1 << pmi
->install_bit
;
96 is_installed
&= pbrms
->installed
;
104 /* If any sequence is installed on the interface, assume installed */
106 pbr_map_interface_is_installed(const struct pbr_map
*pbrm
,
107 const struct pbr_map_interface
*check_pmi
)
110 struct pbr_map_sequence
*pbrms
;
111 struct pbr_map_interface
*pmi
;
112 struct listnode
*node
, *inode
;
114 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
))
115 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, inode
, pmi
))
116 if (pmi
== check_pmi
&& pbrms_is_installed(pbrms
, pmi
))
122 static bool pbr_map_interface_is_valid(const struct pbr_map_interface
*pmi
)
124 /* Don't install rules without a real ifindex on the incoming interface.
126 * This can happen when we have config for an interface that does not
127 * exist or when an interface is changing vrfs.
129 if (pmi
->ifp
&& pmi
->ifp
->ifindex
!= IFINDEX_INTERNAL
)
135 static void pbr_map_pbrms_update_common(struct pbr_map_sequence
*pbrms
,
136 bool install
, bool changed
)
138 struct pbr_map
*pbrm
;
139 struct listnode
*node
;
140 struct pbr_map_interface
*pmi
;
142 pbrm
= pbrms
->parent
;
144 if (pbrms
->nhs_installed
&& pbrm
->incoming
->count
) {
145 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, node
, pmi
)) {
149 if (install
&& !pbr_map_interface_is_valid(pmi
))
152 pbr_send_pbr_map(pbrms
, pmi
, install
, changed
);
157 static void pbr_map_pbrms_install(struct pbr_map_sequence
*pbrms
, bool changed
)
159 pbr_map_pbrms_update_common(pbrms
, true, changed
);
162 static void pbr_map_pbrms_uninstall(struct pbr_map_sequence
*pbrms
)
164 pbr_map_pbrms_update_common(pbrms
, false, false);
167 static const char *const pbr_map_reason_str
[] = {
168 "Invalid NH-group", "Invalid NH", "No Nexthops",
169 "Both NH and NH-Group", "Invalid Src or Dst", "Invalid VRF",
170 "Both VLAN Set and Strip", "Deleting Sequence",
173 void pbr_map_reason_string(unsigned int reason
, char *buf
, int size
)
181 for (bit
= 0; bit
< array_size(pbr_map_reason_str
); bit
++) {
182 if ((reason
& (1 << bit
)) && (len
< size
)) {
183 len
+= snprintf((buf
+ len
), (size
- len
), "%s%s",
184 (len
> 0) ? ", " : "",
185 pbr_map_reason_str
[bit
]);
190 void pbr_map_final_interface_deletion(struct pbr_map
*pbrm
,
191 struct pbr_map_interface
*pmi
)
193 if (pmi
->delete && !pbr_map_interface_is_installed(pbrm
, pmi
)) {
194 listnode_delete(pbrm
->incoming
, pmi
);
197 bf_release_index(pbrm
->ifi_bitfield
, pmi
->install_bit
);
198 XFREE(MTYPE_PBR_MAP_INTERFACE
, pmi
);
202 void pbr_map_interface_delete(struct pbr_map
*pbrm
, struct interface
*ifp_del
)
205 struct listnode
*node
;
206 struct pbr_map_interface
*pmi
;
208 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, node
, pmi
)) {
209 if (ifp_del
== pmi
->ifp
)
214 pbr_map_policy_delete(pbrm
, pmi
);
217 void pbr_map_add_interface(struct pbr_map
*pbrm
, struct interface
*ifp_add
)
219 struct listnode
*node
;
220 struct pbr_map_interface
*pmi
;
222 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, node
, pmi
)) {
223 if (ifp_add
== pmi
->ifp
)
227 pmi
= XCALLOC(MTYPE_PBR_MAP_INTERFACE
, sizeof(*pmi
));
230 listnode_add_sort(pbrm
->incoming
, pmi
);
232 bf_assign_index(pbrm
->ifi_bitfield
, pmi
->install_bit
);
233 pbr_map_check_valid(pbrm
->name
);
235 pbr_map_install(pbrm
);
239 pbr_map_policy_interface_update_common(const struct interface
*ifp
,
240 struct pbr_interface
**pbr_ifp
,
241 struct pbr_map
**pbrm
)
244 DEBUGD(&pbr_dbg_map
, "%s: %s has no pbr_interface info",
245 __func__
, ifp
->name
);
249 *pbr_ifp
= ifp
->info
;
251 *pbrm
= pbrm_find((*pbr_ifp
)->mapname
);
254 DEBUGD(&pbr_dbg_map
, "%s: applied PBR-MAP(%s) does not exist?",
255 __func__
, (*pbr_ifp
)->mapname
);
262 void pbr_map_policy_interface_update(const struct interface
*ifp
, bool state_up
)
264 struct pbr_interface
*pbr_ifp
;
265 struct pbr_map_sequence
*pbrms
;
266 struct pbr_map
*pbrm
;
267 struct listnode
*node
, *inode
;
268 struct pbr_map_interface
*pmi
;
270 if (pbr_map_policy_interface_update_common(ifp
, &pbr_ifp
, &pbrm
))
273 DEBUGD(&pbr_dbg_map
, "%s: %s %s rules on interface %s", __func__
,
274 pbr_ifp
->mapname
, (state_up
? "installing" : "removing"),
278 * Walk the list and install/remove maps on the interface.
280 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
))
281 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, inode
, pmi
))
282 if (pmi
->ifp
== ifp
&& pbr_map_interface_is_valid(pmi
))
283 pbr_send_pbr_map(pbrms
, pmi
, state_up
, true);
286 static void pbrms_vrf_update(struct pbr_map_sequence
*pbrms
,
287 const struct pbr_vrf
*pbr_vrf
)
289 const char *vrf_name
= pbr_vrf_name(pbr_vrf
);
291 if (pbrms
->vrf_lookup
292 && (strncmp(vrf_name
, pbrms
->vrf_name
, sizeof(pbrms
->vrf_name
))
294 DEBUGD(&pbr_dbg_map
, " Seq %u uses vrf %s (%u), updating map",
295 pbrms
->seqno
, vrf_name
, pbr_vrf_id(pbr_vrf
));
297 pbr_map_check(pbrms
, false);
301 /* Vrf enabled/disabled */
302 void pbr_map_vrf_update(const struct pbr_vrf
*pbr_vrf
)
304 struct pbr_map
*pbrm
;
305 struct pbr_map_sequence
*pbrms
;
306 struct listnode
*node
;
311 bool enabled
= pbr_vrf_is_enabled(pbr_vrf
);
313 DEBUGD(&pbr_dbg_map
, "%s: %s (%u) %s, updating pbr maps", __func__
,
314 pbr_vrf_name(pbr_vrf
), pbr_vrf_id(pbr_vrf
),
315 enabled
? "enabled" : "disabled");
317 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
318 DEBUGD(&pbr_dbg_map
, "%s: Looking at %s", __func__
, pbrm
->name
);
319 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
))
320 pbrms_vrf_update(pbrms
, pbr_vrf
);
324 void pbr_map_write_interfaces(struct vty
*vty
, struct interface
*ifp
)
326 struct pbr_interface
*pbr_ifp
= ifp
->info
;
329 && strncmp(pbr_ifp
->mapname
, "", sizeof(pbr_ifp
->mapname
)) != 0)
330 vty_out(vty
, " pbr-policy %s\n", pbr_ifp
->mapname
);
333 struct pbr_map
*pbrm_find(const char *name
)
337 strlcpy(pbrm
.name
, name
, sizeof(pbrm
.name
));
339 return RB_FIND(pbr_map_entry_head
, &pbr_maps
, &pbrm
);
342 extern void pbr_map_delete(struct pbr_map_sequence
*pbrms
)
344 struct pbr_map
*pbrm
;
345 struct listnode
*inode
;
346 struct pbr_map_interface
*pmi
;
348 pbrm
= pbrms
->parent
;
350 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, inode
, pmi
))
351 pbr_send_pbr_map(pbrms
, pmi
, false, false);
354 pbr_nht_delete_individual_nexthop(pbrms
);
356 listnode_delete(pbrm
->seqnumbers
, pbrms
);
358 if (pbrm
->seqnumbers
->count
== 0) {
359 RB_REMOVE(pbr_map_entry_head
, &pbr_maps
, pbrm
);
361 bf_free(pbrm
->ifi_bitfield
);
362 XFREE(MTYPE_PBR_MAP
, pbrm
);
366 static void pbr_map_delete_common(struct pbr_map_sequence
*pbrms
)
368 struct pbr_map
*pbrm
= pbrms
->parent
;
370 pbr_map_pbrms_uninstall(pbrms
);
373 pbrms
->nhs_installed
= false;
374 pbrms
->reason
|= PBR_MAP_INVALID_NO_NEXTHOPS
;
375 XFREE(MTYPE_TMP
, pbrms
->nhgrp_name
);
378 void pbr_map_delete_nexthops(struct pbr_map_sequence
*pbrms
)
380 pbr_map_delete_common(pbrms
);
383 void pbr_map_delete_vrf(struct pbr_map_sequence
*pbrms
)
385 pbr_map_delete_common(pbrms
);
388 struct pbr_map_sequence
*pbrms_lookup_unique(uint32_t unique
, char *ifname
,
389 struct pbr_map_interface
**ppmi
)
391 struct pbr_map_sequence
*pbrms
;
392 struct listnode
*snode
, *inode
;
393 struct pbr_map_interface
*pmi
;
394 struct pbr_map
*pbrm
;
396 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
397 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, inode
, pmi
)) {
398 if (strcmp(pmi
->ifp
->name
, ifname
) != 0)
404 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, snode
,
406 DEBUGD(&pbr_dbg_map
, "%s: Comparing %u to %u",
407 __func__
, pbrms
->unique
, unique
);
408 if (pbrms
->unique
== unique
)
417 static void pbr_map_add_interfaces(struct pbr_map
*pbrm
)
419 struct interface
*ifp
;
420 struct pbr_interface
*pbr_ifp
;
423 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
424 FOR_ALL_INTERFACES (vrf
, ifp
) {
427 if (strcmp(pbrm
->name
, pbr_ifp
->mapname
) == 0)
428 pbr_map_add_interface(pbrm
, ifp
);
434 /* Decodes a standardized DSCP into its representative value */
435 uint8_t pbr_map_decode_dscp_enum(const char *name
)
437 /* Standard Differentiated Services Field Codepoints */
438 if (!strcmp(name
, "cs0"))
440 if (!strcmp(name
, "cs1"))
442 if (!strcmp(name
, "cs2"))
444 if (!strcmp(name
, "cs3"))
446 if (!strcmp(name
, "cs4"))
448 if (!strcmp(name
, "cs5"))
450 if (!strcmp(name
, "cs6"))
452 if (!strcmp(name
, "cs7"))
454 if (!strcmp(name
, "af11"))
456 if (!strcmp(name
, "af12"))
458 if (!strcmp(name
, "af13"))
460 if (!strcmp(name
, "af21"))
462 if (!strcmp(name
, "af22"))
464 if (!strcmp(name
, "af23"))
466 if (!strcmp(name
, "af31"))
468 if (!strcmp(name
, "af32"))
470 if (!strcmp(name
, "af33"))
472 if (!strcmp(name
, "af41"))
474 if (!strcmp(name
, "af42"))
476 if (!strcmp(name
, "af43"))
478 if (!strcmp(name
, "ef"))
480 if (!strcmp(name
, "voice-admit"))
483 /* No match? Error out */
487 struct pbr_map_sequence
*pbrms_get(const char *name
, uint32_t seqno
)
489 struct pbr_map
*pbrm
;
490 struct pbr_map_sequence
*pbrms
;
491 struct listnode
*node
;
493 pbrm
= pbrm_find(name
);
495 pbrm
= XCALLOC(MTYPE_PBR_MAP
, sizeof(*pbrm
));
496 snprintf(pbrm
->name
, sizeof(pbrm
->name
), "%s", name
);
498 pbrm
->seqnumbers
= list_new();
499 pbrm
->seqnumbers
->cmp
=
500 (int (*)(void *, void *))pbr_map_sequence_compare
;
501 pbrm
->seqnumbers
->del
=
502 (void (*)(void *))pbr_map_sequence_delete
;
504 pbrm
->incoming
= list_new();
505 pbrm
->incoming
->cmp
=
506 (int (*)(void *, void *))pbr_map_interface_compare
;
507 pbrm
->incoming
->del
=
508 (void (*)(void *))pbr_map_interface_list_delete
;
510 RB_INSERT(pbr_map_entry_head
, &pbr_maps
, pbrm
);
512 bf_init(pbrm
->ifi_bitfield
, 64);
513 pbr_map_add_interfaces(pbrm
);
516 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
517 if (pbrms
->seqno
== seqno
)
523 pbrms
= XCALLOC(MTYPE_PBR_MAP_SEQNO
, sizeof(*pbrms
));
524 pbrms
->unique
= pbr_map_sequence_unique
++;
525 pbrms
->seqno
= seqno
;
526 pbrms
->ruleno
= pbr_nht_get_next_rule(seqno
);
527 pbrms
->parent
= pbrm
;
529 pbrms
->action_vlan_id
= 0;
530 pbrms
->action_vlan_flags
= 0;
531 pbrms
->action_pcp
= 0;
533 pbrms
->action_queue_id
= PBR_MAP_UNDEFINED_QUEUE_ID
;
536 PBR_MAP_INVALID_EMPTY
|
537 PBR_MAP_INVALID_NO_NEXTHOPS
;
538 pbrms
->vrf_name
[0] = '\0';
540 QOBJ_REG(pbrms
, pbr_map_sequence
);
541 listnode_add_sort(pbrm
->seqnumbers
, pbrms
);
548 pbr_map_sequence_check_nexthops_valid(struct pbr_map_sequence
*pbrms
)
550 /* Check if any are present first */
551 if (!pbrms
->vrf_unchanged
&& !pbrms
->vrf_lookup
&& !pbrms
->nhg
552 && !pbrms
->nhgrp_name
) {
553 pbrms
->reason
|= PBR_MAP_INVALID_NO_NEXTHOPS
;
558 * Check validness of vrf.
561 /* This one can be considered always valid */
562 if (pbrms
->vrf_unchanged
)
563 pbrms
->nhs_installed
= true;
565 if (pbrms
->vrf_lookup
) {
566 struct pbr_vrf
*pbr_vrf
=
567 pbr_vrf_lookup_by_name(pbrms
->vrf_name
);
569 if (pbr_vrf
&& pbr_vrf_is_valid(pbr_vrf
))
570 pbrms
->nhs_installed
= true;
572 pbrms
->reason
|= PBR_MAP_INVALID_VRF
;
576 * Check validness of the nexthop or nexthop-group
579 /* Only nexthop or nexthop group allowed */
580 if (pbrms
->nhg
&& pbrms
->nhgrp_name
)
581 pbrms
->reason
|= PBR_MAP_INVALID_BOTH_NHANDGRP
;
584 !pbr_nht_nexthop_group_valid(pbrms
->internal_nhg_name
))
585 pbrms
->reason
|= PBR_MAP_INVALID_NEXTHOP
;
587 if (pbrms
->nhgrp_name
) {
588 if (!pbr_nht_nexthop_group_valid(pbrms
->nhgrp_name
))
589 pbrms
->reason
|= PBR_MAP_INVALID_NEXTHOP_GROUP
;
591 pbrms
->nhs_installed
= true;
595 static void pbr_map_sequence_check_not_empty(struct pbr_map_sequence
*pbrms
)
597 if (!pbrms
->src
&& !pbrms
->dst
&& !pbrms
->mark
&& !pbrms
->dsfield
598 && !pbrms
->action_vlan_id
&& !pbrms
->action_vlan_flags
599 && !pbrms
->action_pcp
600 && pbrms
->action_queue_id
== PBR_MAP_UNDEFINED_QUEUE_ID
)
601 pbrms
->reason
|= PBR_MAP_INVALID_EMPTY
;
604 static void pbr_map_sequence_check_vlan_actions(struct pbr_map_sequence
*pbrms
)
606 /* The set vlan tag action does the following:
607 * 1. If the frame is untagged, it tags the frame with the
608 * configured VLAN ID.
609 * 2. If the frame is tagged, if replaces the tag.
611 * The strip vlan action removes any inner tag, so it is invalid to
612 * specify both a set and strip action.
614 if ((pbrms
->action_vlan_id
!= 0) && (pbrms
->action_vlan_flags
!= 0))
615 pbrms
->reason
|= PBR_MAP_INVALID_SET_STRIP_VLAN
;
620 * Checks to see if we think that the pbmrs is valid. If we think
621 * the config is valid return true.
623 static void pbr_map_sequence_check_valid(struct pbr_map_sequence
*pbrms
)
625 pbr_map_sequence_check_nexthops_valid(pbrms
);
626 pbr_map_sequence_check_vlan_actions(pbrms
);
627 pbr_map_sequence_check_not_empty(pbrms
);
630 static bool pbr_map_check_valid_internal(struct pbr_map
*pbrm
)
632 struct pbr_map_sequence
*pbrms
;
633 struct listnode
*node
;
636 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
638 pbr_map_sequence_check_valid(pbrms
);
640 * A pbr_map_sequence that is invalid causes
641 * the whole shebang to be invalid
643 if (pbrms
->reason
!= 0)
651 * For a given PBR-MAP check to see if we think it is a
652 * valid config or not. If so note that it is and return
655 bool pbr_map_check_valid(const char *name
)
657 struct pbr_map
*pbrm
;
659 pbrm
= pbrm_find(name
);
662 "%s: Specified PBR-MAP(%s) does not exist?", __func__
,
667 pbr_map_check_valid_internal(pbrm
);
671 void pbr_map_schedule_policy_from_nhg(const char *nh_group
, bool installed
)
673 struct pbr_map_sequence
*pbrms
;
674 struct pbr_map
*pbrm
;
675 struct listnode
*node
;
677 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
678 DEBUGD(&pbr_dbg_map
, "%s: Looking at %s", __func__
, pbrm
->name
);
679 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
680 DEBUGD(&pbr_dbg_map
, " NH Grp name: %s",
682 pbrms
->nhgrp_name
: pbrms
->internal_nhg_name
);
684 if (pbrms
->nhgrp_name
685 && (strcmp(nh_group
, pbrms
->nhgrp_name
) == 0)) {
686 pbrms
->nhs_installed
= installed
;
688 pbr_map_check(pbrms
, false);
692 && (strcmp(nh_group
, pbrms
->internal_nhg_name
)
694 pbrms
->nhs_installed
= installed
;
696 pbr_map_check(pbrms
, false);
702 void pbr_map_policy_install(const char *name
)
704 struct pbr_map_sequence
*pbrms
;
705 struct pbr_map
*pbrm
;
706 struct listnode
*node
, *inode
;
707 struct pbr_map_interface
*pmi
;
709 DEBUGD(&pbr_dbg_map
, "%s: for %s", __func__
, name
);
710 pbrm
= pbrm_find(name
);
714 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
716 "%s: Looking at what to install %s(%u) %d %d", __func__
,
717 name
, pbrms
->seqno
, pbrm
->valid
, pbrms
->nhs_installed
);
719 if (pbrm
->valid
&& pbrms
->nhs_installed
720 && pbrm
->incoming
->count
) {
721 DEBUGD(&pbr_dbg_map
, " Installing %s %u", pbrm
->name
,
723 for (ALL_LIST_ELEMENTS_RO(pbrm
->incoming
, inode
, pmi
))
724 if (pbr_map_interface_is_valid(pmi
))
725 pbr_send_pbr_map(pbrms
, pmi
, true,
731 void pbr_map_policy_delete(struct pbr_map
*pbrm
, struct pbr_map_interface
*pmi
)
733 struct listnode
*node
;
734 struct pbr_map_sequence
*pbrms
;
738 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
))
739 if (pbr_send_pbr_map(pbrms
, pmi
, false, true))
740 sent
= true; /* rule removal sent to zebra */
745 * If we actually sent something for deletion, wait on zapi callback
746 * before clearing data.
751 pbr_map_final_interface_deletion(pbrm
, pmi
);
755 * For a nexthop group specified, see if any of the pbr-maps
756 * are using it and if so, check to see that we are still
757 * valid for usage. If we are valid then schedule the installation/deletion
760 void pbr_map_check_nh_group_change(const char *nh_group
)
762 struct pbr_map_sequence
*pbrms
;
763 struct pbr_map
*pbrm
;
764 struct listnode
*node
, *inode
;
765 struct pbr_map_interface
*pmi
;
768 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
769 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
771 if (pbrms
->nhgrp_name
)
773 !strcmp(nh_group
, pbrms
->nhgrp_name
);
775 found_name
= !strcmp(nh_group
,
776 pbrms
->internal_nhg_name
);
779 bool original
= pbrm
->valid
;
781 /* Set data we were waiting on */
782 if (pbrms
->nhgrp_name
)
783 pbr_nht_set_seq_nhg_data(
785 nhgc_find(pbrms
->nhgrp_name
));
787 pbr_map_check_valid_internal(pbrm
);
789 if (pbrm
->valid
&& (original
!= pbrm
->valid
))
790 pbr_map_install(pbrm
);
792 if (pbrm
->valid
== false)
793 for (ALL_LIST_ELEMENTS_RO(
794 pbrm
->incoming
, inode
,
796 pbr_send_pbr_map(pbrms
, pmi
,
803 void pbr_map_check_vrf_nh_group_change(const char *nh_group
,
804 struct pbr_vrf
*pbr_vrf
,
807 struct pbr_map
*pbrm
;
808 struct pbr_map_sequence
*pbrms
;
809 struct listnode
*node
;
812 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
813 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
814 if (pbrms
->nhgrp_name
)
817 if (pbrms
->nhg
== NULL
)
820 if (strcmp(nh_group
, pbrms
->internal_nhg_name
))
823 if (pbrms
->nhg
->nexthop
== NULL
)
826 if (pbrms
->nhg
->nexthop
->vrf_id
!= old_vrf_id
)
829 pbrms
->nhg
->nexthop
->vrf_id
= pbr_vrf_id(pbr_vrf
);
834 void pbr_map_check_interface_nh_group_change(const char *nh_group
,
835 struct interface
*ifp
,
836 ifindex_t oldifindex
)
838 struct pbr_map
*pbrm
;
839 struct pbr_map_sequence
*pbrms
;
840 struct listnode
*node
;
842 RB_FOREACH (pbrm
, pbr_map_entry_head
, &pbr_maps
) {
843 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
)) {
844 if (pbrms
->nhgrp_name
)
847 if (pbrms
->nhg
== NULL
)
850 if (strcmp(nh_group
, pbrms
->internal_nhg_name
))
853 if (pbrms
->nhg
->nexthop
== NULL
)
856 if (pbrms
->nhg
->nexthop
->ifindex
!= oldifindex
)
859 pbrms
->nhg
->nexthop
->ifindex
= ifp
->ifindex
;
864 void pbr_map_check(struct pbr_map_sequence
*pbrms
, bool changed
)
866 struct pbr_map
*pbrm
;
869 pbrm
= pbrms
->parent
;
870 DEBUGD(&pbr_dbg_map
, "%s: for %s(%u)", __func__
, pbrm
->name
,
872 if (pbr_map_check_valid(pbrm
->name
))
873 DEBUGD(&pbr_dbg_map
, "We are totally valid %s",
876 if (pbrms
->reason
== PBR_MAP_VALID_SEQUENCE_NUMBER
) {
878 DEBUGD(&pbr_dbg_map
, "%s: Installing %s(%u) reason: %" PRIu64
,
879 __func__
, pbrm
->name
, pbrms
->seqno
, pbrms
->reason
);
881 " Sending PBR_MAP_POLICY_INSTALL event");
884 DEBUGD(&pbr_dbg_map
, "%s: Removing %s(%u) reason: %" PRIu64
,
885 __func__
, pbrm
->name
, pbrms
->seqno
, pbrms
->reason
);
889 pbr_map_pbrms_install(pbrms
, changed
);
891 pbr_map_pbrms_uninstall(pbrms
);
894 void pbr_map_install(struct pbr_map
*pbrm
)
896 struct pbr_map_sequence
*pbrms
;
897 struct listnode
*node
;
899 if (!pbrm
->incoming
->count
)
902 for (ALL_LIST_ELEMENTS_RO(pbrm
->seqnumbers
, node
, pbrms
))
903 pbr_map_pbrms_install(pbrms
, false);
906 void pbr_map_init(void)
908 RB_INIT(pbr_map_entry_head
, &pbr_maps
);
910 pbr_map_sequence_unique
= 1;