]> git.proxmox.com Git - mirror_frr.git/blob - pbrd/pbr_map.c
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[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 QOBJ_UNREG(pbrms);
79 XFREE(MTYPE_PBR_MAP_SEQNO, pbrms);
80 }
81
82 static int pbr_map_interface_compare(const struct pbr_map_interface *pmi1,
83 const struct pbr_map_interface *pmi2)
84 {
85 return strcmp(pmi1->ifp->name, pmi2->ifp->name);
86 }
87
88 static void pbr_map_interface_list_delete(struct pbr_map_interface *pmi)
89 {
90 struct pbr_map_interface *pmi_int;
91 struct listnode *node, *nnode;
92 struct pbr_map *pbrm;
93
94 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
95 for (ALL_LIST_ELEMENTS(pbrm->incoming, node, nnode, pmi_int)) {
96 if (pmi == pmi_int) {
97 pbr_map_policy_delete(pbrm, pmi);
98 return;
99 }
100 }
101 }
102 }
103
104 static bool pbrms_is_installed(const struct pbr_map_sequence *pbrms,
105 const struct pbr_map_interface *pmi)
106 {
107 uint64_t is_installed = (uint64_t)1 << pmi->install_bit;
108
109 is_installed &= pbrms->installed;
110
111 if (is_installed)
112 return true;
113
114 return false;
115 }
116
117 /* If any sequence is installed on the interface, assume installed */
118 static bool
119 pbr_map_interface_is_installed(const struct pbr_map *pbrm,
120 const struct pbr_map_interface *check_pmi)
121 {
122
123 struct pbr_map_sequence *pbrms;
124 struct pbr_map_interface *pmi;
125 struct listnode *node, *inode;
126
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))
130 return true;
131
132 return false;
133 }
134
135 static bool pbr_map_interface_is_valid(const struct pbr_map_interface *pmi)
136 {
137 /* Don't install rules without a real ifindex on the incoming interface.
138 *
139 * This can happen when we have config for an interface that does not
140 * exist or when an interface is changing vrfs.
141 */
142 if (pmi->ifp && pmi->ifp->ifindex != IFINDEX_INTERNAL)
143 return true;
144
145 return false;
146 }
147
148 static void pbr_map_pbrms_update_common(struct pbr_map_sequence *pbrms,
149 bool install, bool changed)
150 {
151 struct pbr_map *pbrm;
152 struct listnode *node;
153 struct pbr_map_interface *pmi;
154
155 pbrm = pbrms->parent;
156
157 if (pbrms->nhs_installed && pbrm->incoming->count) {
158 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) {
159 if (!pmi->ifp)
160 continue;
161
162 if (install && !pbr_map_interface_is_valid(pmi))
163 continue;
164
165 pbr_send_pbr_map(pbrms, pmi, install, changed);
166 }
167 }
168 }
169
170 static void pbr_map_pbrms_install(struct pbr_map_sequence *pbrms, bool changed)
171 {
172 pbr_map_pbrms_update_common(pbrms, true, changed);
173 }
174
175 static void pbr_map_pbrms_uninstall(struct pbr_map_sequence *pbrms)
176 {
177 pbr_map_pbrms_update_common(pbrms, false, false);
178 }
179
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",
183 "Both VLAN Set and Strip", "Deleting Sequence",
184 };
185
186 void pbr_map_reason_string(unsigned int reason, char *buf, int size)
187 {
188 unsigned int bit;
189 int len = 0;
190
191 if (!buf)
192 return;
193
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]);
199 }
200 }
201 }
202
203 void pbr_map_final_interface_deletion(struct pbr_map *pbrm,
204 struct pbr_map_interface *pmi)
205 {
206 if (pmi->delete && !pbr_map_interface_is_installed(pbrm, pmi)) {
207 listnode_delete(pbrm->incoming, pmi);
208 pmi->pbrm = NULL;
209
210 bf_release_index(pbrm->ifi_bitfield, pmi->install_bit);
211 XFREE(MTYPE_PBR_MAP_INTERFACE, pmi);
212 }
213 }
214
215 void pbr_map_interface_delete(struct pbr_map *pbrm, struct interface *ifp_del)
216 {
217
218 struct listnode *node;
219 struct pbr_map_interface *pmi;
220
221 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) {
222 if (ifp_del == pmi->ifp)
223 break;
224 }
225
226 if (pmi)
227 pbr_map_policy_delete(pbrm, pmi);
228 }
229
230 void pbr_map_add_interface(struct pbr_map *pbrm, struct interface *ifp_add)
231 {
232 struct listnode *node;
233 struct pbr_map_interface *pmi;
234
235 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) {
236 if (ifp_add == pmi->ifp)
237 return;
238 }
239
240 pmi = XCALLOC(MTYPE_PBR_MAP_INTERFACE, sizeof(*pmi));
241 pmi->ifp = ifp_add;
242 pmi->pbrm = pbrm;
243 listnode_add_sort(pbrm->incoming, pmi);
244
245 bf_assign_index(pbrm->ifi_bitfield, pmi->install_bit);
246 pbr_map_check_valid(pbrm->name);
247 if (pbrm->valid)
248 pbr_map_install(pbrm);
249 }
250
251 static int
252 pbr_map_policy_interface_update_common(const struct interface *ifp,
253 struct pbr_interface **pbr_ifp,
254 struct pbr_map **pbrm)
255 {
256 if (!ifp->info) {
257 DEBUGD(&pbr_dbg_map, "%s: %s has no pbr_interface info",
258 __func__, ifp->name);
259 return -1;
260 }
261
262 *pbr_ifp = ifp->info;
263
264 *pbrm = pbrm_find((*pbr_ifp)->mapname);
265
266 if (!*pbrm) {
267 DEBUGD(&pbr_dbg_map, "%s: applied PBR-MAP(%s) does not exist?",
268 __func__, (*pbr_ifp)->mapname);
269 return -1;
270 }
271
272 return 0;
273 }
274
275 void pbr_map_policy_interface_update(const struct interface *ifp, bool state_up)
276 {
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;
282
283 if (pbr_map_policy_interface_update_common(ifp, &pbr_ifp, &pbrm))
284 return;
285
286 DEBUGD(&pbr_dbg_map, "%s: %s %s rules on interface %s", __func__,
287 pbr_ifp->mapname, (state_up ? "installing" : "removing"),
288 ifp->name);
289
290 /*
291 * Walk the list and install/remove maps on the interface.
292 */
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);
297 }
298
299 static void pbrms_vrf_update(struct pbr_map_sequence *pbrms,
300 const struct pbr_vrf *pbr_vrf)
301 {
302 const char *vrf_name = pbr_vrf_name(pbr_vrf);
303
304 if (pbrms->vrf_lookup
305 && (strncmp(vrf_name, pbrms->vrf_name, sizeof(pbrms->vrf_name))
306 == 0)) {
307 DEBUGD(&pbr_dbg_map, " Seq %u uses vrf %s (%u), updating map",
308 pbrms->seqno, vrf_name, pbr_vrf_id(pbr_vrf));
309
310 pbr_map_check(pbrms, false);
311 }
312 }
313
314 /* Vrf enabled/disabled */
315 void pbr_map_vrf_update(const struct pbr_vrf *pbr_vrf)
316 {
317 struct pbr_map *pbrm;
318 struct pbr_map_sequence *pbrms;
319 struct listnode *node;
320
321 if (!pbr_vrf)
322 return;
323
324 bool enabled = pbr_vrf_is_enabled(pbr_vrf);
325
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");
329
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);
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, 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 XFREE(MTYPE_TMP, pbrms->nhgrp_name);
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, char *ifname,
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 (strcmp(pmi->ifp->name, ifname) != 0)
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 __func__, pbrms->unique, unique);
421 if (pbrms->unique == unique)
422 return pbrms;
423 }
424 }
425 }
426
427 return NULL;
428 }
429
430 static void pbr_map_add_interfaces(struct pbr_map *pbrm)
431 {
432 struct interface *ifp;
433 struct pbr_interface *pbr_ifp;
434 struct vrf *vrf;
435
436 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
437 FOR_ALL_INTERFACES (vrf, ifp) {
438 if (ifp->info) {
439 pbr_ifp = ifp->info;
440 if (strcmp(pbrm->name, pbr_ifp->mapname) == 0)
441 pbr_map_add_interface(pbrm, ifp);
442 }
443 }
444 }
445 }
446
447 /* Decodes a standardized DSCP into its representative value */
448 uint8_t pbr_map_decode_dscp_enum(const char *name)
449 {
450 /* Standard Differentiated Services Field Codepoints */
451 if (!strcmp(name, "cs0"))
452 return 0;
453 if (!strcmp(name, "cs1"))
454 return 8;
455 if (!strcmp(name, "cs2"))
456 return 16;
457 if (!strcmp(name, "cs3"))
458 return 24;
459 if (!strcmp(name, "cs4"))
460 return 32;
461 if (!strcmp(name, "cs5"))
462 return 40;
463 if (!strcmp(name, "cs6"))
464 return 48;
465 if (!strcmp(name, "cs7"))
466 return 56;
467 if (!strcmp(name, "af11"))
468 return 10;
469 if (!strcmp(name, "af12"))
470 return 12;
471 if (!strcmp(name, "af13"))
472 return 14;
473 if (!strcmp(name, "af21"))
474 return 18;
475 if (!strcmp(name, "af22"))
476 return 20;
477 if (!strcmp(name, "af23"))
478 return 22;
479 if (!strcmp(name, "af31"))
480 return 26;
481 if (!strcmp(name, "af32"))
482 return 28;
483 if (!strcmp(name, "af33"))
484 return 30;
485 if (!strcmp(name, "af41"))
486 return 34;
487 if (!strcmp(name, "af42"))
488 return 36;
489 if (!strcmp(name, "af43"))
490 return 38;
491 if (!strcmp(name, "ef"))
492 return 46;
493 if (!strcmp(name, "voice-admit"))
494 return 44;
495
496 /* No match? Error out */
497 return -1;
498 }
499
500 struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno)
501 {
502 struct pbr_map *pbrm;
503 struct pbr_map_sequence *pbrms;
504 struct listnode *node;
505
506 pbrm = pbrm_find(name);
507 if (!pbrm) {
508 pbrm = XCALLOC(MTYPE_PBR_MAP, sizeof(*pbrm));
509 snprintf(pbrm->name, sizeof(pbrm->name), "%s", name);
510
511 pbrm->seqnumbers = list_new();
512 pbrm->seqnumbers->cmp =
513 (int (*)(void *, void *))pbr_map_sequence_compare;
514 pbrm->seqnumbers->del =
515 (void (*)(void *))pbr_map_sequence_delete;
516
517 pbrm->incoming = list_new();
518 pbrm->incoming->cmp =
519 (int (*)(void *, void *))pbr_map_interface_compare;
520 pbrm->incoming->del =
521 (void (*)(void *))pbr_map_interface_list_delete;
522
523 RB_INSERT(pbr_map_entry_head, &pbr_maps, pbrm);
524
525 bf_init(pbrm->ifi_bitfield, 64);
526 pbr_map_add_interfaces(pbrm);
527 }
528
529 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
530 if (pbrms->seqno == seqno)
531 break;
532
533 }
534
535 if (!pbrms) {
536 pbrms = XCALLOC(MTYPE_PBR_MAP_SEQNO, sizeof(*pbrms));
537 pbrms->unique = pbr_map_sequence_unique++;
538 pbrms->seqno = seqno;
539 pbrms->ruleno = pbr_nht_get_next_rule(seqno);
540 pbrms->parent = pbrm;
541
542 pbrms->action_vlan_id = 0;
543 pbrms->action_vlan_flags = 0;
544 pbrms->action_pcp = 0;
545
546 pbrms->action_queue_id = PBR_MAP_UNDEFINED_QUEUE_ID;
547
548 pbrms->reason =
549 PBR_MAP_INVALID_EMPTY |
550 PBR_MAP_INVALID_NO_NEXTHOPS;
551 pbrms->vrf_name[0] = '\0';
552
553 QOBJ_REG(pbrms, pbr_map_sequence);
554 listnode_add_sort(pbrm->seqnumbers, pbrms);
555 }
556
557 return pbrms;
558 }
559
560 static void
561 pbr_map_sequence_check_nexthops_valid(struct pbr_map_sequence *pbrms)
562 {
563 /* Check if any are present first */
564 if (!pbrms->vrf_unchanged && !pbrms->vrf_lookup && !pbrms->nhg
565 && !pbrms->nhgrp_name) {
566 pbrms->reason |= PBR_MAP_INVALID_NO_NEXTHOPS;
567 return;
568 }
569
570 /*
571 * Check validness of vrf.
572 */
573
574 /* This one can be considered always valid */
575 if (pbrms->vrf_unchanged)
576 pbrms->nhs_installed = true;
577
578 if (pbrms->vrf_lookup) {
579 struct pbr_vrf *pbr_vrf =
580 pbr_vrf_lookup_by_name(pbrms->vrf_name);
581
582 if (pbr_vrf && pbr_vrf_is_valid(pbr_vrf))
583 pbrms->nhs_installed = true;
584 else
585 pbrms->reason |= PBR_MAP_INVALID_VRF;
586 }
587
588 /*
589 * Check validness of the nexthop or nexthop-group
590 */
591
592 /* Only nexthop or nexthop group allowed */
593 if (pbrms->nhg && pbrms->nhgrp_name)
594 pbrms->reason |= PBR_MAP_INVALID_BOTH_NHANDGRP;
595
596 if (pbrms->nhg &&
597 !pbr_nht_nexthop_group_valid(pbrms->internal_nhg_name))
598 pbrms->reason |= PBR_MAP_INVALID_NEXTHOP;
599
600 if (pbrms->nhgrp_name) {
601 if (!pbr_nht_nexthop_group_valid(pbrms->nhgrp_name))
602 pbrms->reason |= PBR_MAP_INVALID_NEXTHOP_GROUP;
603 else
604 pbrms->nhs_installed = true;
605 }
606 }
607
608 static void pbr_map_sequence_check_not_empty(struct pbr_map_sequence *pbrms)
609 {
610 if (!pbrms->src && !pbrms->dst && !pbrms->mark && !pbrms->dsfield
611 && !pbrms->action_vlan_id && !pbrms->action_vlan_flags
612 && !pbrms->action_pcp
613 && pbrms->action_queue_id == PBR_MAP_UNDEFINED_QUEUE_ID)
614 pbrms->reason |= PBR_MAP_INVALID_EMPTY;
615 }
616
617 static void pbr_map_sequence_check_vlan_actions(struct pbr_map_sequence *pbrms)
618 {
619 /* The set vlan tag action does the following:
620 * 1. If the frame is untagged, it tags the frame with the
621 * configured VLAN ID.
622 * 2. If the frame is tagged, if replaces the tag.
623 *
624 * The strip vlan action removes any inner tag, so it is invalid to
625 * specify both a set and strip action.
626 */
627 if ((pbrms->action_vlan_id != 0) && (pbrms->action_vlan_flags != 0))
628 pbrms->reason |= PBR_MAP_INVALID_SET_STRIP_VLAN;
629 }
630
631
632 /*
633 * Checks to see if we think that the pbmrs is valid. If we think
634 * the config is valid return true.
635 */
636 static void pbr_map_sequence_check_valid(struct pbr_map_sequence *pbrms)
637 {
638 pbr_map_sequence_check_nexthops_valid(pbrms);
639 pbr_map_sequence_check_vlan_actions(pbrms);
640 pbr_map_sequence_check_not_empty(pbrms);
641 }
642
643 static bool pbr_map_check_valid_internal(struct pbr_map *pbrm)
644 {
645 struct pbr_map_sequence *pbrms;
646 struct listnode *node;
647
648 pbrm->valid = true;
649 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
650 pbrms->reason = 0;
651 pbr_map_sequence_check_valid(pbrms);
652 /*
653 * A pbr_map_sequence that is invalid causes
654 * the whole shebang to be invalid
655 */
656 if (pbrms->reason != 0)
657 pbrm->valid = false;
658 }
659
660 return pbrm->valid;
661 }
662
663 /*
664 * For a given PBR-MAP check to see if we think it is a
665 * valid config or not. If so note that it is and return
666 * that we are valid.
667 */
668 bool pbr_map_check_valid(const char *name)
669 {
670 struct pbr_map *pbrm;
671
672 pbrm = pbrm_find(name);
673 if (!pbrm) {
674 DEBUGD(&pbr_dbg_map,
675 "%s: Specified PBR-MAP(%s) does not exist?", __func__,
676 name);
677 return false;
678 }
679
680 pbr_map_check_valid_internal(pbrm);
681 return pbrm->valid;
682 }
683
684 void pbr_map_schedule_policy_from_nhg(const char *nh_group, bool installed)
685 {
686 struct pbr_map_sequence *pbrms;
687 struct pbr_map *pbrm;
688 struct listnode *node;
689
690 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
691 DEBUGD(&pbr_dbg_map, "%s: Looking at %s", __func__, pbrm->name);
692 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
693 DEBUGD(&pbr_dbg_map, " NH Grp name: %s",
694 pbrms->nhgrp_name ?
695 pbrms->nhgrp_name : pbrms->internal_nhg_name);
696
697 if (pbrms->nhgrp_name
698 && (strcmp(nh_group, pbrms->nhgrp_name) == 0)) {
699 pbrms->nhs_installed = installed;
700
701 pbr_map_check(pbrms, false);
702 }
703
704 if (pbrms->nhg
705 && (strcmp(nh_group, pbrms->internal_nhg_name)
706 == 0)) {
707 pbrms->nhs_installed = installed;
708
709 pbr_map_check(pbrms, false);
710 }
711 }
712 }
713 }
714
715 void pbr_map_policy_install(const char *name)
716 {
717 struct pbr_map_sequence *pbrms;
718 struct pbr_map *pbrm;
719 struct listnode *node, *inode;
720 struct pbr_map_interface *pmi;
721
722 DEBUGD(&pbr_dbg_map, "%s: for %s", __func__, name);
723 pbrm = pbrm_find(name);
724 if (!pbrm)
725 return;
726
727 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
728 DEBUGD(&pbr_dbg_map,
729 "%s: Looking at what to install %s(%u) %d %d", __func__,
730 name, pbrms->seqno, pbrm->valid, pbrms->nhs_installed);
731
732 if (pbrm->valid && pbrms->nhs_installed
733 && pbrm->incoming->count) {
734 DEBUGD(&pbr_dbg_map, " Installing %s %u", pbrm->name,
735 pbrms->seqno);
736 for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi))
737 if (pbr_map_interface_is_valid(pmi))
738 pbr_send_pbr_map(pbrms, pmi, true,
739 false);
740 }
741 }
742 }
743
744 void pbr_map_policy_delete(struct pbr_map *pbrm, struct pbr_map_interface *pmi)
745 {
746 struct listnode *node;
747 struct pbr_map_sequence *pbrms;
748 bool sent = false;
749
750
751 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
752 if (pbr_send_pbr_map(pbrms, pmi, false, true))
753 sent = true; /* rule removal sent to zebra */
754
755 pmi->delete = true;
756
757 /*
758 * If we actually sent something for deletion, wait on zapi callback
759 * before clearing data.
760 */
761 if (sent)
762 return;
763
764 pbr_map_final_interface_deletion(pbrm, pmi);
765 }
766
767 /*
768 * For a nexthop group specified, see if any of the pbr-maps
769 * are using it and if so, check to see that we are still
770 * valid for usage. If we are valid then schedule the installation/deletion
771 * of the pbr-policy.
772 */
773 void pbr_map_check_nh_group_change(const char *nh_group)
774 {
775 struct pbr_map_sequence *pbrms;
776 struct pbr_map *pbrm;
777 struct listnode *node, *inode;
778 struct pbr_map_interface *pmi;
779 bool found_name;
780
781 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
782 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
783 found_name = false;
784 if (pbrms->nhgrp_name)
785 found_name =
786 !strcmp(nh_group, pbrms->nhgrp_name);
787 else if (pbrms->nhg)
788 found_name = !strcmp(nh_group,
789 pbrms->internal_nhg_name);
790
791 if (found_name) {
792 bool original = pbrm->valid;
793
794 /* Set data we were waiting on */
795 if (pbrms->nhgrp_name)
796 pbr_nht_set_seq_nhg_data(
797 pbrms,
798 nhgc_find(pbrms->nhgrp_name));
799
800 pbr_map_check_valid_internal(pbrm);
801
802 if (pbrm->valid && (original != pbrm->valid))
803 pbr_map_install(pbrm);
804
805 if (pbrm->valid == false)
806 for (ALL_LIST_ELEMENTS_RO(
807 pbrm->incoming, inode,
808 pmi))
809 pbr_send_pbr_map(pbrms, pmi,
810 false, false);
811 }
812 }
813 }
814 }
815
816 void pbr_map_check_vrf_nh_group_change(const char *nh_group,
817 struct pbr_vrf *pbr_vrf,
818 uint32_t old_vrf_id)
819 {
820 struct pbr_map *pbrm;
821 struct pbr_map_sequence *pbrms;
822 struct listnode *node;
823
824
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)
828 continue;
829
830 if (pbrms->nhg == NULL)
831 continue;
832
833 if (strcmp(nh_group, pbrms->internal_nhg_name))
834 continue;
835
836 if (pbrms->nhg->nexthop == NULL)
837 continue;
838
839 if (pbrms->nhg->nexthop->vrf_id != old_vrf_id)
840 continue;
841
842 pbrms->nhg->nexthop->vrf_id = pbr_vrf_id(pbr_vrf);
843 }
844 }
845 }
846
847 void pbr_map_check_interface_nh_group_change(const char *nh_group,
848 struct interface *ifp,
849 ifindex_t oldifindex)
850 {
851 struct pbr_map *pbrm;
852 struct pbr_map_sequence *pbrms;
853 struct listnode *node;
854
855 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
856 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
857 if (pbrms->nhgrp_name)
858 continue;
859
860 if (pbrms->nhg == NULL)
861 continue;
862
863 if (strcmp(nh_group, pbrms->internal_nhg_name))
864 continue;
865
866 if (pbrms->nhg->nexthop == NULL)
867 continue;
868
869 if (pbrms->nhg->nexthop->ifindex != oldifindex)
870 continue;
871
872 pbrms->nhg->nexthop->ifindex = ifp->ifindex;
873 }
874 }
875 }
876
877 void pbr_map_check(struct pbr_map_sequence *pbrms, bool changed)
878 {
879 struct pbr_map *pbrm;
880 bool install;
881
882 pbrm = pbrms->parent;
883 DEBUGD(&pbr_dbg_map, "%s: for %s(%u)", __func__, pbrm->name,
884 pbrms->seqno);
885 if (pbr_map_check_valid(pbrm->name))
886 DEBUGD(&pbr_dbg_map, "We are totally valid %s",
887 pbrm->name);
888
889 if (pbrms->reason == PBR_MAP_VALID_SEQUENCE_NUMBER) {
890 install = true;
891 DEBUGD(&pbr_dbg_map, "%s: Installing %s(%u) reason: %" PRIu64,
892 __func__, pbrm->name, pbrms->seqno, pbrms->reason);
893 DEBUGD(&pbr_dbg_map,
894 " Sending PBR_MAP_POLICY_INSTALL event");
895 } else {
896 install = false;
897 DEBUGD(&pbr_dbg_map, "%s: Removing %s(%u) reason: %" PRIu64,
898 __func__, pbrm->name, pbrms->seqno, pbrms->reason);
899 }
900
901 if (install)
902 pbr_map_pbrms_install(pbrms, changed);
903 else
904 pbr_map_pbrms_uninstall(pbrms);
905 }
906
907 void pbr_map_install(struct pbr_map *pbrm)
908 {
909 struct pbr_map_sequence *pbrms;
910 struct listnode *node;
911
912 if (!pbrm->incoming->count)
913 return;
914
915 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
916 pbr_map_pbrms_install(pbrms, false);
917 }
918
919 void pbr_map_init(void)
920 {
921 RB_INIT(pbr_map_entry_head, &pbr_maps);
922
923 pbr_map_sequence_unique = 1;
924 }