]>
Commit | Line | Data |
---|---|---|
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" | |
35 | #include "pbr_event.h" | |
36 | #include "pbr_zebra.h" | |
37 | #include "pbr_memory.h" | |
38 | #include "pbr_debug.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 | ||
d3765386 DS |
46 | static inline int pbr_map_compare(const struct pbr_map *pbrmap1, |
47 | const struct pbr_map *pbrmap2); | |
e5c83d9b DS |
48 | |
49 | RB_GENERATE(pbr_map_entry_head, pbr_map, pbr_map_entry, pbr_map_compare) | |
50 | ||
51 | struct pbr_map_entry_head pbr_maps = RB_INITIALIZER(&pbr_maps); | |
52 | ||
53 | DEFINE_QOBJ_TYPE(pbr_map_sequence) | |
54 | ||
d3765386 DS |
55 | static inline int pbr_map_compare(const struct pbr_map *pbrmap1, |
56 | const struct pbr_map *pbrmap2) | |
e5c83d9b DS |
57 | { |
58 | return strcmp(pbrmap1->name, pbrmap2->name); | |
59 | } | |
60 | ||
61 | static int pbr_map_sequence_compare(const struct pbr_map_sequence *pbrms1, | |
62 | const struct pbr_map_sequence *pbrms2) | |
63 | { | |
64 | if (pbrms1->seqno == pbrms2->seqno) | |
65 | return 0; | |
66 | ||
67 | if (pbrms1->seqno < pbrms2->seqno) | |
68 | return -1; | |
69 | ||
70 | return 1; | |
71 | } | |
72 | ||
73 | static void pbr_map_sequence_delete(struct pbr_map_sequence *pbrms) | |
74 | { | |
75 | if (pbrms->internal_nhg_name) | |
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(const struct pbr_map_interface *pmi) | |
88 | { | |
89 | pbr_map_policy_delete(pmi->ifp->name); | |
90 | } | |
91 | ||
92 | static const char *pbr_map_reason_str[] = { | |
93 | "Invalid NH-group", "Invalid NH", "No Nexthops", | |
94 | "Both NH and NH-Group", "Invalid Src or Dst", "Deleting Sequence", | |
95 | }; | |
96 | ||
97 | void pbr_map_reason_string(unsigned int reason, char *buf, int size) | |
98 | { | |
99 | unsigned int bit; | |
100 | int len = 0; | |
101 | ||
102 | if (!buf) | |
103 | return; | |
104 | ||
105 | for (bit = 0; bit < array_size(pbr_map_reason_str); bit++) { | |
106 | if ((reason & (1 << bit)) && (len < size)) { | |
107 | len += snprintf((buf + len), (size - len), "%s%s", | |
108 | (len > 0) ? ", " : "", | |
109 | pbr_map_reason_str[bit]); | |
110 | } | |
111 | } | |
112 | } | |
113 | ||
114 | ||
115 | void pbr_map_interface_delete(struct pbr_map *pbrm, struct interface *ifp_del) | |
116 | { | |
117 | ||
118 | struct listnode *node; | |
119 | struct pbr_map_interface *pmi; | |
120 | struct pbr_event *pbre; | |
121 | ||
122 | for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) { | |
123 | if (ifp_del == pmi->ifp) | |
124 | break; | |
125 | } | |
126 | ||
127 | if (pmi) { | |
128 | pmi->delete = true; | |
129 | ||
130 | pbre = pbr_event_new(PBR_POLICY_DELETED, pmi->ifp->name); | |
131 | pbr_event_enqueue(pbre); | |
132 | } | |
133 | } | |
134 | ||
135 | void pbr_map_add_interface(struct pbr_map *pbrm, struct interface *ifp_add) | |
136 | { | |
137 | struct listnode *node; | |
138 | struct pbr_map_interface *pmi; | |
139 | struct pbr_event *pbre; | |
140 | ||
141 | for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, node, pmi)) { | |
142 | if (ifp_add == pmi->ifp) | |
143 | return; | |
144 | } | |
145 | ||
146 | pmi = XCALLOC(MTYPE_PBR_MAP_INTERFACE, sizeof(*pmi)); | |
147 | pmi->ifp = ifp_add; | |
148 | pmi->pbrm = pbrm; | |
149 | listnode_add_sort(pbrm->incoming, pmi); | |
150 | ||
151 | pbre = pbr_event_new(PBR_POLICY_CHANGED, pbrm->name); | |
152 | pbr_event_enqueue(pbre); | |
153 | } | |
154 | ||
155 | void pbr_map_write_interfaces(struct vty *vty, struct interface *ifp) | |
156 | { | |
157 | struct pbr_interface *pbr_ifp = ifp->info; | |
158 | ||
159 | if (!(strcmp(pbr_ifp->mapname, "") == 0)) | |
160 | vty_out(vty, " pbr-policy %s\n", pbr_ifp->mapname); | |
161 | } | |
162 | ||
163 | struct pbr_map *pbrm_find(const char *name) | |
164 | { | |
165 | struct pbr_map pbrm; | |
166 | ||
167 | strlcpy(pbrm.name, name, sizeof(pbrm.name)); | |
168 | ||
169 | return RB_FIND(pbr_map_entry_head, &pbr_maps, &pbrm); | |
170 | } | |
171 | ||
172 | extern void pbr_map_delete(const char *name, uint32_t seqno) | |
173 | { | |
174 | struct pbr_map *pbrm; | |
175 | struct pbr_map_sequence *pbrms; | |
176 | struct listnode *node, *nnode; | |
177 | bool uninstall = false; | |
178 | ||
179 | pbrm = pbrm_find(name); | |
180 | ||
181 | for (ALL_LIST_ELEMENTS(pbrm->seqnumbers, node, nnode, pbrms)) { | |
182 | if (pbrms->reason & PBR_MAP_DEL_SEQUENCE_NUMBER) { | |
183 | uninstall = true; | |
184 | break; | |
185 | } | |
186 | } | |
187 | ||
188 | if (uninstall) | |
189 | pbr_send_pbr_map(pbrm, 0); | |
190 | ||
191 | for (ALL_LIST_ELEMENTS(pbrm->seqnumbers, node, nnode, pbrms)) { | |
192 | if (!(pbrms->reason & PBR_MAP_DEL_SEQUENCE_NUMBER)) | |
193 | continue; | |
194 | ||
195 | if (pbrms->nhg) | |
196 | pbr_nht_delete_individual_nexthop(pbrms->parent->name, | |
197 | pbrms->seqno); | |
198 | ||
199 | listnode_delete(pbrm->seqnumbers, pbrms); | |
200 | } | |
201 | ||
202 | if (pbrm->seqnumbers->count == 0) { | |
203 | RB_REMOVE(pbr_map_entry_head, &pbr_maps, pbrm); | |
204 | XFREE(MTYPE_PBR_MAP, pbrm); | |
205 | } | |
206 | } | |
207 | ||
d3765386 DS |
208 | struct pbr_map_sequence *pbrms_lookup_unique(uint32_t unique, |
209 | ifindex_t ifindex) | |
e5c83d9b DS |
210 | { |
211 | struct pbr_map_sequence *pbrms; | |
212 | struct listnode *snode, *inode; | |
213 | struct pbr_map_interface *pmi; | |
214 | struct pbr_map *pbrm; | |
215 | ||
216 | RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) { | |
217 | for (ALL_LIST_ELEMENTS_RO(pbrm->incoming, inode, pmi)) { | |
218 | if (pmi->ifp->ifindex != ifindex) | |
219 | continue; | |
220 | ||
221 | for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, snode, | |
222 | pbrms)) { | |
223 | DEBUGD(&pbr_dbg_map, "%s: Comparing %u to %u", | |
224 | __PRETTY_FUNCTION__, pbrms->unique, | |
225 | unique); | |
226 | if (pbrms->unique == unique) | |
227 | return pbrms; | |
228 | } | |
229 | } | |
230 | } | |
231 | ||
232 | return NULL; | |
233 | } | |
234 | ||
d3765386 | 235 | struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno) |
e5c83d9b DS |
236 | { |
237 | struct pbr_map *pbrm; | |
238 | struct pbr_map_sequence *pbrms; | |
239 | struct listnode *node; | |
240 | struct pbr_event *pbre; | |
241 | ||
242 | pbrm = pbrm_find(name); | |
243 | if (!pbrm) { | |
244 | pbrm = XCALLOC(MTYPE_PBR_MAP, sizeof(*pbrm)); | |
245 | strcpy(pbrm->name, name); | |
246 | ||
247 | pbrm->seqnumbers = list_new(); | |
248 | pbrm->seqnumbers->cmp = | |
249 | (int (*)(void *, void *))pbr_map_sequence_compare; | |
250 | pbrm->seqnumbers->del = | |
251 | (void (*)(void *))pbr_map_sequence_delete; | |
252 | ||
253 | pbrm->incoming = list_new(); | |
254 | pbrm->incoming->cmp = | |
255 | (int (*)(void *, void *))pbr_map_interface_compare; | |
256 | pbrm->incoming->del = | |
257 | (void (*)(void *))pbr_map_interface_list_delete; | |
258 | ||
259 | RB_INSERT(pbr_map_entry_head, &pbr_maps, pbrm); | |
260 | ||
261 | pbre = pbr_event_new(PBR_MAP_ADD, name); | |
262 | } else | |
263 | pbre = NULL; | |
264 | ||
265 | for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) { | |
266 | if (pbrms->seqno == seqno) | |
267 | break; | |
268 | ||
269 | } | |
270 | ||
271 | if (!pbrms) { | |
272 | pbrms = XCALLOC(MTYPE_PBR_MAP_SEQNO, sizeof(*pbrms)); | |
273 | pbrms->unique = pbr_map_sequence_unique++; | |
274 | pbrms->seqno = seqno; | |
275 | pbrms->ruleno = pbr_nht_get_next_rule(seqno); | |
276 | pbrms->parent = pbrm; | |
277 | pbrms->reason = | |
278 | PBR_MAP_INVALID_SRCDST | | |
279 | PBR_MAP_INVALID_NO_NEXTHOPS; | |
280 | ||
281 | QOBJ_REG(pbrms, pbr_map_sequence); | |
282 | listnode_add_sort(pbrm->seqnumbers, pbrms); | |
283 | ||
284 | pbrm->installed = false; | |
285 | } | |
286 | ||
287 | if (pbre) | |
288 | pbr_event_enqueue(pbre); | |
289 | ||
290 | return pbrms; | |
291 | } | |
292 | ||
293 | static void | |
294 | pbr_map_sequence_check_nexthops_valid(struct pbr_map_sequence *pbrms) | |
295 | { | |
296 | /* | |
297 | * Check validness of the nexthop or nexthop-group | |
298 | */ | |
299 | if (!pbrms->nhg && !pbrms->nhgrp_name) | |
300 | pbrms->reason |= PBR_MAP_INVALID_NO_NEXTHOPS; | |
301 | ||
302 | if (pbrms->nhg && pbrms->nhgrp_name) | |
303 | pbrms->reason |= PBR_MAP_INVALID_BOTH_NHANDGRP; | |
304 | ||
305 | if (pbrms->nhg && | |
306 | !pbr_nht_nexthop_group_valid(pbrms->internal_nhg_name)) | |
307 | pbrms->reason |= PBR_MAP_INVALID_NEXTHOP; | |
308 | ||
309 | if (pbrms->nhgrp_name) { | |
310 | if (!pbr_nht_nexthop_group_valid(pbrms->nhgrp_name)) | |
311 | pbrms->reason |= PBR_MAP_INVALID_NEXTHOP_GROUP; | |
312 | else | |
313 | pbrms->nhs_installed = true; | |
314 | } | |
315 | } | |
316 | ||
317 | static void pbr_map_sequence_check_src_dst_valid(struct pbr_map_sequence *pbrms) | |
318 | { | |
319 | if (!pbrms->src && !pbrms->dst) | |
320 | pbrms->reason |= PBR_MAP_INVALID_SRCDST; | |
321 | } | |
322 | ||
323 | /* | |
324 | * Checks to see if we think that the pbmrs is valid. If we think | |
325 | * the config is valid return true. | |
326 | */ | |
327 | static void pbr_map_sequence_check_valid(struct pbr_map_sequence *pbrms) | |
328 | { | |
329 | pbr_map_sequence_check_nexthops_valid(pbrms); | |
330 | ||
331 | pbr_map_sequence_check_src_dst_valid(pbrms); | |
332 | } | |
333 | ||
334 | static bool pbr_map_check_valid_internal(struct pbr_map *pbrm) | |
335 | { | |
336 | struct pbr_map_sequence *pbrms; | |
337 | struct listnode *node; | |
338 | ||
339 | pbrm->valid = true; | |
340 | for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) { | |
341 | pbrms->reason = 0; | |
342 | pbr_map_sequence_check_valid(pbrms); | |
343 | /* | |
344 | * A pbr_map_sequence that is invalid causes | |
345 | * the whole shebang to be invalid | |
346 | */ | |
347 | if (pbrms->reason != 0) | |
348 | pbrm->valid = false; | |
349 | } | |
350 | ||
351 | return pbrm->valid; | |
352 | } | |
353 | ||
354 | /* | |
355 | * For a given PBR-MAP check to see if we think it is a | |
356 | * valid config or not. If so note that it is and return | |
357 | * that we are valid. | |
358 | */ | |
d3765386 | 359 | bool pbr_map_check_valid(const char *name) |
e5c83d9b DS |
360 | { |
361 | struct pbr_map *pbrm; | |
362 | ||
363 | pbrm = pbrm_find(name); | |
364 | if (!pbrm) { | |
365 | DEBUGD(&pbr_dbg_map, | |
366 | "%s: Specified PBR-MAP(%s) does not exist?", | |
367 | __PRETTY_FUNCTION__, name); | |
368 | return false; | |
369 | } | |
370 | ||
371 | pbr_map_check_valid_internal(pbrm); | |
372 | return pbrm->valid; | |
373 | } | |
374 | ||
d3765386 | 375 | void pbr_map_schedule_policy_from_nhg(const char *nh_group) |
e5c83d9b DS |
376 | { |
377 | struct pbr_map_sequence *pbrms; | |
378 | struct pbr_event *pbre; | |
379 | struct pbr_map *pbrm; | |
380 | struct listnode *node; | |
381 | ||
382 | RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) { | |
383 | DEBUGD(&pbr_dbg_map, "%s: Looking at %s", __PRETTY_FUNCTION__, | |
384 | pbrm->name); | |
385 | for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) { | |
386 | DEBUGD(&pbr_dbg_map, "\tNH Grp name: %s", | |
387 | pbrms->nhgrp_name ? pbrms->nhgrp_name : "NULL"); | |
388 | ||
389 | if (pbrms->nhgrp_name | |
390 | && (strcmp(nh_group, pbrms->nhgrp_name) == 0)) { | |
391 | pbrms->nhs_installed = true; | |
392 | ||
393 | pbre = pbr_event_new(PBR_MAP_MODIFY, | |
394 | pbrm->name); | |
395 | pbre->seqno = pbrms->seqno; | |
396 | ||
397 | pbr_event_enqueue(pbre); | |
398 | } | |
399 | ||
400 | if (pbrms->nhg | |
401 | && (strcmp(nh_group, pbrms->internal_nhg_name) | |
402 | == 0)) { | |
403 | pbrms->nhs_installed = true; | |
404 | ||
405 | pbre = pbr_event_new(PBR_MAP_MODIFY, | |
406 | pbrm->name); | |
407 | pbre->seqno = pbrms->seqno; | |
408 | ||
409 | pbr_event_enqueue(pbre); | |
410 | } | |
411 | } | |
412 | } | |
413 | } | |
414 | ||
d3765386 | 415 | void pbr_map_policy_install(const char *name) |
e5c83d9b DS |
416 | { |
417 | struct pbr_map_sequence *pbrms; | |
418 | struct pbr_map *pbrm; | |
419 | struct listnode *node; | |
420 | bool install; | |
421 | ||
422 | DEBUGD(&pbr_dbg_map, "%s: for %s", __PRETTY_FUNCTION__, name); | |
423 | pbrm = pbrm_find(name); | |
424 | if (!pbrm) | |
425 | return; | |
426 | ||
427 | install = true; | |
428 | for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) { | |
429 | DEBUGD(&pbr_dbg_map, | |
430 | "%s: Looking at what to install %s(%u) %d %d", | |
431 | __PRETTY_FUNCTION__, name, pbrms->seqno, pbrm->valid, | |
432 | pbrms->nhs_installed); | |
433 | if (!pbrm->valid || !pbrms->nhs_installed) | |
434 | install = false; | |
435 | } | |
436 | ||
437 | if (install && pbrm->incoming->count) { | |
438 | DEBUGD(&pbr_dbg_map, "\tInstalling"); | |
439 | pbr_send_pbr_map(pbrm, true); | |
440 | } | |
441 | } | |
442 | ||
d3765386 | 443 | void pbr_map_policy_delete(const char *ifname) |
e5c83d9b DS |
444 | { |
445 | struct listnode *node, *nnode; | |
446 | struct pbr_map_interface *pmi; | |
447 | struct pbr_map *pbrm; | |
448 | ||
449 | RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) { | |
450 | for (ALL_LIST_ELEMENTS(pbrm->incoming, node, nnode, pmi)) { | |
451 | DEBUGD(&pbr_dbg_map, "Comparing %s to %s %d", | |
452 | pmi->ifp->name, ifname, pmi->delete); | |
453 | if (strcmp(ifname, pmi->ifp->name) != 0) | |
454 | continue; | |
455 | ||
456 | pbr_send_pbr_map(pbrm, false); | |
457 | listnode_delete(pbrm->incoming, pmi); | |
458 | pmi->pbrm = NULL; | |
459 | XFREE(MTYPE_PBR_MAP_INTERFACE, pmi); | |
460 | } | |
461 | } | |
462 | } | |
463 | ||
464 | /* | |
465 | * For a nexthop group specified, see if any of the pbr-maps | |
466 | * are using it and if so, check to see that we are still | |
467 | * valid for usage. If we are valid then schedule the installation/deletion | |
468 | * of the pbr-policy. | |
469 | */ | |
d3765386 | 470 | void pbr_map_check_nh_group_change(const char *nh_group) |
e5c83d9b DS |
471 | { |
472 | struct pbr_map_sequence *pbrms; | |
473 | struct pbr_map *pbrm; | |
474 | struct listnode *node; | |
475 | bool found_name; | |
476 | ||
477 | zlog_warn("*** %s for %s ***", __func__, nh_group); | |
478 | RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) { | |
479 | for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) { | |
480 | found_name = false; | |
481 | if (pbrms->nhgrp_name) | |
482 | found_name = | |
483 | !strcmp(nh_group, pbrms->nhgrp_name); | |
484 | else if (pbrms->nhg) | |
485 | found_name = !strcmp(nh_group, | |
486 | pbrms->internal_nhg_name); | |
487 | ||
488 | if (found_name) { | |
489 | bool original = pbrm->valid; | |
e5c83d9b DS |
490 | |
491 | pbr_map_check_valid_internal(pbrm); | |
492 | ||
493 | if (original != pbrm->valid) { | |
494 | struct pbr_event *pbre; | |
495 | ||
496 | pbre = pbr_event_new(PBR_MAP_INSTALL, | |
497 | pbrm->name); | |
498 | pbr_event_enqueue(pbre); | |
499 | } | |
500 | break; | |
501 | } | |
502 | } | |
503 | } | |
504 | } | |
505 | ||
d3765386 | 506 | void pbr_map_check(const char *name, uint32_t seqno) |
e5c83d9b DS |
507 | { |
508 | struct pbr_map_sequence *pbrms; | |
509 | struct listnode *node; | |
510 | struct pbr_map *pbrm; | |
511 | ||
512 | DEBUGD(&pbr_dbg_map, "%s: for %s(%u)", __PRETTY_FUNCTION__, name, | |
513 | seqno); | |
514 | if (pbr_map_check_valid(name)) | |
515 | DEBUGD(&pbr_dbg_map, "We are totally valid %s\n", name); | |
516 | ||
517 | pbrm = pbrm_find(name); | |
518 | if (!pbrm) | |
519 | return; | |
520 | ||
521 | for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) { | |
522 | if (seqno != pbrms->seqno) | |
523 | continue; | |
524 | ||
525 | DEBUGD(&pbr_dbg_map, "%s: Installing %s(%u) reason: %" PRIu64, | |
526 | __PRETTY_FUNCTION__, name, seqno, pbrms->reason); | |
527 | ||
528 | if (pbrms->reason == PBR_MAP_VALID_SEQUENCE_NUMBER) { | |
529 | struct pbr_event *pbre; | |
530 | ||
531 | DEBUGD(&pbr_dbg_map, | |
532 | "%s: Installing %s(%u) reason: %" PRIu64, | |
533 | __PRETTY_FUNCTION__, name, seqno, pbrms->reason); | |
534 | DEBUGD(&pbr_dbg_map, | |
535 | "\tSending PBR_MAP_POLICY_INSTALL event"); | |
536 | ||
537 | pbre = pbr_event_new(PBR_MAP_POLICY_INSTALL, | |
538 | pbrm->name); | |
539 | pbre->event = PBR_MAP_POLICY_INSTALL; | |
540 | strcpy(pbre->name, pbrm->name); | |
541 | ||
542 | pbr_event_enqueue(pbre); | |
543 | ||
544 | break; | |
545 | } else { | |
546 | DEBUGD(&pbr_dbg_map, | |
547 | "%s: Removing %s(%u) reason: %" PRIu64, | |
548 | __PRETTY_FUNCTION__, name, seqno, pbrms->reason); | |
549 | pbr_send_pbr_map(pbrm, false); | |
550 | break; | |
551 | } | |
552 | } | |
553 | } | |
554 | ||
d3765386 | 555 | void pbr_map_install(const char *name) |
e5c83d9b DS |
556 | { |
557 | struct pbr_map *pbrm; | |
558 | ||
559 | pbrm = pbrm_find(name); | |
560 | if (!pbrm) { | |
561 | DEBUGD(&pbr_dbg_map, | |
562 | "%s: Specified PBR-MAP(%s) does not exist?", | |
563 | __PRETTY_FUNCTION__, name); | |
564 | return; | |
565 | } | |
566 | ||
567 | if (!pbrm->incoming->count) | |
568 | return; | |
569 | ||
570 | pbr_send_pbr_map(pbrm, true); | |
571 | pbrm->installed = true; | |
572 | } | |
573 | ||
d3765386 | 574 | void pbr_map_add_interfaces(const char *name) |
e5c83d9b DS |
575 | { |
576 | struct pbr_map *pbrm; | |
577 | struct interface *ifp; | |
578 | struct pbr_interface *pbr_ifp; | |
579 | struct vrf *vrf; | |
580 | ||
581 | pbrm = pbrm_find(name); | |
582 | if (!pbrm) { | |
583 | DEBUGD(&pbr_dbg_map, | |
584 | "%s: Specified PBR-MAP(%s) does not exist?", | |
585 | __PRETTY_FUNCTION__, name); | |
586 | return; | |
587 | } | |
588 | ||
589 | RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { | |
d3765386 | 590 | FOR_ALL_INTERFACES (vrf, ifp) { |
e5c83d9b DS |
591 | if (ifp->info) { |
592 | pbr_ifp = ifp->info; | |
593 | if (strcmp(name, pbr_ifp->mapname) == 0) | |
594 | pbr_map_add_interface(pbrm, ifp); | |
595 | } | |
596 | } | |
597 | } | |
598 | } | |
599 | ||
d3765386 | 600 | void pbr_map_check_policy_change(const char *name) |
e5c83d9b DS |
601 | { |
602 | struct pbr_map *pbrm; | |
603 | ||
604 | pbrm = pbrm_find(name); | |
605 | if (!pbrm) { | |
606 | DEBUGD(&pbr_dbg_map, | |
607 | "%s: Specified PBR-MAP(%s) does not exist?", | |
608 | __PRETTY_FUNCTION__, name); | |
609 | return; | |
610 | } | |
611 | ||
612 | pbr_map_check_valid(name); | |
613 | if (pbrm->valid && !pbrm->installed) { | |
614 | struct pbr_event *pbre; | |
615 | ||
616 | pbre = pbr_event_new(PBR_MAP_INSTALL, name); | |
617 | ||
618 | pbr_event_enqueue(pbre); | |
619 | } | |
620 | } | |
621 | ||
d3765386 | 622 | void pbr_map_init(void) |
e5c83d9b DS |
623 | { |
624 | RB_INIT(pbr_map_entry_head, &pbr_maps); | |
625 | ||
626 | pbr_map_sequence_unique = 1; | |
627 | } |