blob: 6caeb1b69283e765a76d225dc9fa113c6b30a2cc [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
74static int
75mfib_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
82 /* continue */
83 return (1);
84}
85
86void
87mfib_entry_cover_walk (mfib_entry_t *cover,
88 mfib_entry_covered_walk_t walk,
89 void *args)
90{
91 mfib_entry_delegate_t *mfed;
92
93 mfed = mfib_entry_delegate_get(cover, MFIB_ENTRY_DELEGATE_COVERED);
94
95 if (NULL == mfed)
96 return;
97
98 mfib_enty_cover_walk_ctx_t ctx = {
99 .cover = cover,
100 .walk = walk,
101 .ctx = args,
102 };
103
104 fib_node_list_walk(mfed->mfd_list,
105 mfib_entry_cover_walk_node_ptr,
106 &ctx);
107}
108
109static int
110mfib_entry_cover_change_one (mfib_entry_t *cover,
111 fib_node_index_t covered,
112 void *args)
113{
114 fib_node_index_t new_cover;
115
116 /*
117 * The 3 entries involved here are:
118 * cover - the least specific. It will cover both the others
119 * new_cover - the enty just inserted below the cover
120 * covered - the entry that was tracking the cover.
121 *
122 * The checks below are to determine if new_cover is a cover for covered.
123 */
124 new_cover = pointer_to_uword(args);
125
126 if (FIB_NODE_INDEX_INVALID == new_cover)
127 {
128 /*
129 * nothing has been inserted, which implies the cover was removed.
130 * 'cover' is thus the new cover.
131 */
132 mfib_entry_cover_changed(covered);
133 }
134 else if (new_cover != covered)
135 {
136 const mfib_prefix_t *pfx_covered, *pfx_new_cover;
137
138 pfx_covered = mfib_entry_get_prefix(covered);
139 pfx_new_cover = mfib_entry_get_prefix(new_cover);
140
141 if (mfib_prefix_is_cover(pfx_new_cover, pfx_covered))
142 {
143 mfib_entry_cover_changed(covered);
144 }
145 }
146 /* continue */
147 return (1);
148}
149
150void
151mfib_entry_cover_change_notify (fib_node_index_t cover_index,
152 fib_node_index_t covered)
153{
154 mfib_entry_t *cover;
155
156 cover = mfib_entry_get(cover_index);
157
158 mfib_entry_cover_walk(cover,
159 mfib_entry_cover_change_one,
160 uword_to_pointer(covered, void*));
161}
162
163static int
164mfib_entry_cover_update_one (mfib_entry_t *cover,
165 fib_node_index_t covered,
166 void *args)
167{
168 mfib_entry_cover_updated(covered);
169
170 /* continue */
171 return (1);
172}
173
174void
175mfib_entry_cover_update_notify (mfib_entry_t *mfib_entry)
176{
177 mfib_entry_cover_walk(mfib_entry,
178 mfib_entry_cover_update_one,
179 NULL);
180}