blob: 2f5fd6bad08387e9927952b056ced2c988b21435 [file] [log] [blame]
Neale Ranns9e829a82018-12-17 05:50:32 -08001/*
2 * Copyright (c) 2016 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <vnet/mfib/mfib_entry_cover.h>
17#include <vnet/mfib/mfib_entry_src.h>
18#include <vnet/fib/fib_node_list.h>
19
20u32
21mfib_entry_cover_track (mfib_entry_t* cover,
22 fib_node_index_t covered)
23{
24 mfib_entry_delegate_t *mfed;
25
26 MFIB_ENTRY_DBG(cover, "cover-track %d", covered);
27
28 ASSERT(mfib_entry_get_index(cover) != covered);
29
30 mfed = mfib_entry_delegate_get(cover, MFIB_ENTRY_DELEGATE_COVERED);
31
32 if (NULL == mfed)
33 {
34 mfed = mfib_entry_delegate_find_or_add(cover, MFIB_ENTRY_DELEGATE_COVERED);
35 mfed->mfd_list = fib_node_list_create();
36 }
37
38 return (fib_node_list_push_front(mfed->mfd_list,
39 0, FIB_NODE_TYPE_MFIB_ENTRY,
40 covered));
41}
42
43void
44mfib_entry_cover_untrack (mfib_entry_t* cover,
45 u32 tracked_index)
46{
47 mfib_entry_delegate_t *mfed;
48
49 MFIB_ENTRY_DBG(cover, "cover-untrack @ %d", tracked_index);
50
51 mfed = mfib_entry_delegate_get(cover, MFIB_ENTRY_DELEGATE_COVERED);
52
53 if (NULL == mfed)
54 return;
55
56 fib_node_list_remove(mfed->mfd_list, tracked_index);
57
58 if (0 == fib_node_list_get_size(mfed->mfd_list))
59 {
60 fib_node_list_destroy(&mfed->mfd_list);
61 mfib_entry_delegate_remove(cover, MFIB_ENTRY_DELEGATE_COVERED);
62 }
63}
64
65/**
66 * Internal struct to hold user supplied paraneters for the cover walk
67 */
68typedef struct mfib_enty_cover_walk_ctx_t_ {
69 mfib_entry_t *cover;
70 mfib_entry_covered_walk_t walk;
71 void *ctx;
72} mfib_enty_cover_walk_ctx_t;
73
Neale Rannsfdf6b6f2020-11-26 09:34:39 +000074static walk_rc_t
Neale Ranns9e829a82018-12-17 05:50:32 -080075mfib_entry_cover_walk_node_ptr (fib_node_ptr_t *depend,
76 void *args)
77{
78 mfib_enty_cover_walk_ctx_t *ctx = args;
79
80 ctx->walk(ctx->cover, depend->fnp_index, ctx->ctx);
81
Neale Rannsfdf6b6f2020-11-26 09:34:39 +000082 return (WALK_CONTINUE);
Neale Ranns9e829a82018-12-17 05:50:32 -080083}
84
85void
86mfib_entry_cover_walk (mfib_entry_t *cover,
87 mfib_entry_covered_walk_t walk,
88 void *args)
89{
90 mfib_entry_delegate_t *mfed;
91
92 mfed = mfib_entry_delegate_get(cover, MFIB_ENTRY_DELEGATE_COVERED);
93
94 if (NULL == mfed)
95 return;
96
97 mfib_enty_cover_walk_ctx_t ctx = {
98 .cover = cover,
99 .walk = walk,
100 .ctx = args,
101 };
102
103 fib_node_list_walk(mfed->mfd_list,
104 mfib_entry_cover_walk_node_ptr,
105 &ctx);
106}
107
108static int
109mfib_entry_cover_change_one (mfib_entry_t *cover,
110 fib_node_index_t covered,
111 void *args)
112{
113 fib_node_index_t new_cover;
114
115 /*
116 * The 3 entries involved here are:
117 * cover - the least specific. It will cover both the others
118 * new_cover - the enty just inserted below the cover
119 * covered - the entry that was tracking the cover.
120 *
121 * The checks below are to determine if new_cover is a cover for covered.
122 */
123 new_cover = pointer_to_uword(args);
124
125 if (FIB_NODE_INDEX_INVALID == new_cover)
126 {
127 /*
128 * nothing has been inserted, which implies the cover was removed.
129 * 'cover' is thus the new cover.
130 */
131 mfib_entry_cover_changed(covered);
132 }
133 else if (new_cover != covered)
134 {
135 const mfib_prefix_t *pfx_covered, *pfx_new_cover;
136
137 pfx_covered = mfib_entry_get_prefix(covered);
138 pfx_new_cover = mfib_entry_get_prefix(new_cover);
139
140 if (mfib_prefix_is_cover(pfx_new_cover, pfx_covered))
141 {
142 mfib_entry_cover_changed(covered);
143 }
144 }
145 /* continue */
146 return (1);
147}
148
149void
150mfib_entry_cover_change_notify (fib_node_index_t cover_index,
151 fib_node_index_t covered)
152{
153 mfib_entry_t *cover;
154
155 cover = mfib_entry_get(cover_index);
156
157 mfib_entry_cover_walk(cover,
158 mfib_entry_cover_change_one,
159 uword_to_pointer(covered, void*));
160}
161
162static int
163mfib_entry_cover_update_one (mfib_entry_t *cover,
164 fib_node_index_t covered,
165 void *args)
166{
167 mfib_entry_cover_updated(covered);
168
169 /* continue */
170 return (1);
171}
172
173void
174mfib_entry_cover_update_notify (mfib_entry_t *mfib_entry)
175{
176 mfib_entry_cover_walk(mfib_entry,
177 mfib_entry_cover_update_one,
178 NULL);
179}