blob: 147c5daa4fd125617dbce3c792d2d5aa509dcb5a [file] [log] [blame]
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001/*
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/fib/fib_entry_cover.h>
17#include <vnet/fib/fib_entry_src.h>
18#include <vnet/fib/fib_node_list.h>
19
20u32
21fib_entry_cover_track (fib_entry_t* cover,
22 fib_node_index_t covered)
23{
Neale Rannsad422ed2016-11-02 14:20:04 +000024 fib_entry_delegate_t *fed;
25
Neale Ranns0bfe5d82016-08-25 15:29:12 +010026 FIB_ENTRY_DBG(cover, "cover-track %d", covered);
27
28 ASSERT(fib_entry_get_index(cover) != covered);
29
Neale Rannsad422ed2016-11-02 14:20:04 +000030 fed = fib_entry_delegate_get(cover, FIB_ENTRY_DELEGATE_COVERED);
31
32 if (NULL == fed)
Neale Ranns0bfe5d82016-08-25 15:29:12 +010033 {
Neale Rannsad422ed2016-11-02 14:20:04 +000034 fed = fib_entry_delegate_find_or_add(cover, FIB_ENTRY_DELEGATE_COVERED);
35 fed->fd_list = fib_node_list_create();
Neale Ranns0bfe5d82016-08-25 15:29:12 +010036 }
37
Neale Rannsad422ed2016-11-02 14:20:04 +000038 return (fib_node_list_push_front(fed->fd_list,
Neale Ranns0bfe5d82016-08-25 15:29:12 +010039 0, FIB_NODE_TYPE_ENTRY,
40 covered));
41}
42
43void
44fib_entry_cover_untrack (fib_entry_t* cover,
45 u32 tracked_index)
46{
Neale Rannsad422ed2016-11-02 14:20:04 +000047 fib_entry_delegate_t *fed;
48
Neale Ranns0bfe5d82016-08-25 15:29:12 +010049 FIB_ENTRY_DBG(cover, "cover-untrack @ %d", tracked_index);
50
Neale Rannsad422ed2016-11-02 14:20:04 +000051 fed = fib_entry_delegate_get(cover, FIB_ENTRY_DELEGATE_COVERED);
52
53 if (NULL == fed)
Neale Ranns0bfe5d82016-08-25 15:29:12 +010054 return;
55
Neale Rannsad422ed2016-11-02 14:20:04 +000056 fib_node_list_remove(fed->fd_list, tracked_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +010057
Neale Rannsad422ed2016-11-02 14:20:04 +000058 if (0 == fib_node_list_get_size(fed->fd_list))
Neale Ranns0bfe5d82016-08-25 15:29:12 +010059 {
Neale Rannsad422ed2016-11-02 14:20:04 +000060 fib_node_list_destroy(&fed->fd_list);
61 fib_entry_delegate_remove(cover, FIB_ENTRY_DELEGATE_COVERED);
Neale Ranns0bfe5d82016-08-25 15:29:12 +010062 }
63}
64
65/**
66 * Internal struct to hold user supplied paraneters for the cover walk
67 */
68typedef struct fib_enty_cover_walk_ctx_t_ {
69 fib_entry_t *cover;
70 fib_entry_covered_walk_t walk;
71 void *ctx;
72} fib_enty_cover_walk_ctx_t;
73
74static int
75fib_entry_cover_walk_node_ptr (fib_node_ptr_t *depend,
76 void *args)
77{
78 fib_enty_cover_walk_ctx_t *ctx = args;
79
80 ctx->walk(ctx->cover, depend->fnp_index, ctx->ctx);
81
82 /* continue */
83 return (1);
84}
85
86void
87fib_entry_cover_walk (fib_entry_t *cover,
88 fib_entry_covered_walk_t walk,
89 void *args)
90{
Neale Rannsad422ed2016-11-02 14:20:04 +000091 fib_entry_delegate_t *fed;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010092
Neale Rannsad422ed2016-11-02 14:20:04 +000093 fed = fib_entry_delegate_get(cover, FIB_ENTRY_DELEGATE_COVERED);
94
95 if (NULL == fed)
96 return;
97
98 fib_enty_cover_walk_ctx_t ctx = {
99 .cover = cover,
100 .walk = walk,
101 .ctx = args,
102 };
103
104 fib_node_list_walk(fed->fd_list,
105 fib_entry_cover_walk_node_ptr,
106 &ctx);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100107}
108
109u32
110fib_entry_cover_get_size (fib_entry_t *cover)
111{
Neale Rannsad422ed2016-11-02 14:20:04 +0000112 fib_entry_delegate_t *fed;
113
114 fed = fib_entry_delegate_get(cover, FIB_ENTRY_DELEGATE_COVERED);
115
116 if (NULL == fed)
117 return (0);
118
119 return (fib_node_list_get_size(fed->fd_list));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100120}
121
122typedef struct fib_entry_cover_list_format_ctx_t_ {
123 u8 *s;
124} fib_entry_cover_list_format_ctx_t;
125
126static int
127fib_entry_covered_list_format_one (fib_entry_t *cover,
128 fib_node_index_t covered,
129 void *args)
130{
131 fib_entry_cover_list_format_ctx_t * ctx = args;
132
133 ctx->s = format(ctx->s, "%d, ", covered);
134
135 /* continue */
136 return (1);
137}
138
139u8*
140fib_entry_cover_list_format (fib_entry_t *fib_entry,
141 u8 *s)
142{
143 fib_entry_cover_list_format_ctx_t ctx = {
144 .s = s,
145 };
146
147 fib_entry_cover_walk(fib_entry,
148 fib_entry_covered_list_format_one,
149 &ctx);
150
151 return (ctx.s);
152}
153
154static int
155fib_entry_cover_change_one (fib_entry_t *cover,
156 fib_node_index_t covered,
157 void *args)
158{
159 fib_node_index_t new_cover;
160
161 /*
162 * The 3 entries involved here are:
163 * cover - the least specific. It will cover both the others
164 * new_cover - the enty just inserted below the cover
165 * covered - the entry that was tracking the cover.
166 *
167 * The checks below are to determine if new_cover is a cover for covered.
168 */
169 new_cover = pointer_to_uword(args);
170
171 if (FIB_NODE_INDEX_INVALID == new_cover)
172 {
173 /*
174 * nothing has been inserted, which implies the cover was removed.
175 * 'cover' is thus the new cover.
176 */
177 fib_entry_cover_changed(covered);
178 }
179 else if (new_cover != covered)
180 {
181 fib_prefix_t pfx_covered, pfx_new_cover;
182
183 fib_entry_get_prefix(covered, &pfx_covered);
184 fib_entry_get_prefix(new_cover, &pfx_new_cover);
185
186 if (fib_prefix_is_cover(&pfx_new_cover, &pfx_covered))
187 {
188 fib_entry_cover_changed(covered);
189 }
190 }
191 /* continue */
192 return (1);
193}
194
195void
196fib_entry_cover_change_notify (fib_node_index_t cover_index,
197 fib_node_index_t covered)
198{
199 fib_entry_t *cover;
200
201 cover = fib_entry_get(cover_index);
202
203 fib_entry_cover_walk(cover,
204 fib_entry_cover_change_one,
205 uword_to_pointer(covered, void*));
206}
207
208static int
209fib_entry_cover_update_one (fib_entry_t *cover,
210 fib_node_index_t covered,
211 void *args)
212{
213 fib_entry_cover_updated(covered);
214
215 /* continue */
216 return (1);
217}
218
219void
220fib_entry_cover_update_notify (fib_entry_t *fib_entry)
221{
222 fib_entry_cover_walk(fib_entry,
223 fib_entry_cover_update_one,
224 NULL);
225}