Line data Source code
1 : /*
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 :
20 : u32
21 8 : mfib_entry_cover_track (mfib_entry_t* cover,
22 : fib_node_index_t covered)
23 : {
24 : mfib_entry_delegate_t *mfed;
25 :
26 8 : MFIB_ENTRY_DBG(cover, "cover-track %d", covered);
27 :
28 8 : ASSERT(mfib_entry_get_index(cover) != covered);
29 :
30 8 : mfed = mfib_entry_delegate_get(cover, MFIB_ENTRY_DELEGATE_COVERED);
31 :
32 8 : if (NULL == mfed)
33 : {
34 8 : mfed = mfib_entry_delegate_find_or_add(cover, MFIB_ENTRY_DELEGATE_COVERED);
35 8 : mfed->mfd_list = fib_node_list_create();
36 : }
37 :
38 8 : return (fib_node_list_push_front(mfed->mfd_list,
39 : 0, FIB_NODE_TYPE_MFIB_ENTRY,
40 : covered));
41 : }
42 :
43 : void
44 8 : mfib_entry_cover_untrack (mfib_entry_t* cover,
45 : u32 tracked_index)
46 : {
47 : mfib_entry_delegate_t *mfed;
48 :
49 8 : MFIB_ENTRY_DBG(cover, "cover-untrack @ %d", tracked_index);
50 :
51 8 : mfed = mfib_entry_delegate_get(cover, MFIB_ENTRY_DELEGATE_COVERED);
52 :
53 8 : if (NULL == mfed)
54 0 : return;
55 :
56 8 : fib_node_list_remove(mfed->mfd_list, tracked_index);
57 :
58 8 : if (0 == fib_node_list_get_size(mfed->mfd_list))
59 : {
60 8 : fib_node_list_destroy(&mfed->mfd_list);
61 8 : 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 : */
68 : typedef 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 :
74 : static walk_rc_t
75 24 : mfib_entry_cover_walk_node_ptr (fib_node_ptr_t *depend,
76 : void *args)
77 : {
78 24 : mfib_enty_cover_walk_ctx_t *ctx = args;
79 :
80 24 : ctx->walk(ctx->cover, depend->fnp_index, ctx->ctx);
81 :
82 24 : return (WALK_CONTINUE);
83 : }
84 :
85 : void
86 99622 : mfib_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 99622 : mfed = mfib_entry_delegate_get(cover, MFIB_ENTRY_DELEGATE_COVERED);
93 :
94 99622 : if (NULL == mfed)
95 99598 : return;
96 :
97 24 : mfib_enty_cover_walk_ctx_t ctx = {
98 : .cover = cover,
99 : .walk = walk,
100 : .ctx = args,
101 : };
102 :
103 24 : fib_node_list_walk(mfed->mfd_list,
104 : mfib_entry_cover_walk_node_ptr,
105 : &ctx);
106 : }
107 :
108 : static int
109 6 : mfib_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 6 : new_cover = pointer_to_uword(args);
124 :
125 6 : 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 2 : mfib_entry_cover_changed(covered);
132 : }
133 4 : else if (new_cover != covered)
134 : {
135 : const mfib_prefix_t *pfx_covered, *pfx_new_cover;
136 :
137 2 : pfx_covered = mfib_entry_get_prefix(covered);
138 2 : pfx_new_cover = mfib_entry_get_prefix(new_cover);
139 :
140 2 : if (mfib_prefix_is_cover(pfx_new_cover, pfx_covered))
141 : {
142 2 : mfib_entry_cover_changed(covered);
143 : }
144 : }
145 : /* continue */
146 6 : return (1);
147 : }
148 :
149 : void
150 11046 : mfib_entry_cover_change_notify (fib_node_index_t cover_index,
151 : fib_node_index_t covered)
152 : {
153 : mfib_entry_t *cover;
154 :
155 11046 : cover = mfib_entry_get(cover_index);
156 :
157 11046 : mfib_entry_cover_walk(cover,
158 : mfib_entry_cover_change_one,
159 11046 : uword_to_pointer(covered, void*));
160 11046 : }
161 :
162 : static int
163 18 : mfib_entry_cover_update_one (mfib_entry_t *cover,
164 : fib_node_index_t covered,
165 : void *args)
166 : {
167 18 : mfib_entry_cover_updated(covered);
168 :
169 : /* continue */
170 18 : return (1);
171 : }
172 :
173 : void
174 88576 : mfib_entry_cover_update_notify (mfib_entry_t *mfib_entry)
175 : {
176 88576 : mfib_entry_cover_walk(mfib_entry,
177 : mfib_entry_cover_update_one,
178 : NULL);
179 88576 : }
|