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