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/fib/fib_entry_cover.h>
17 : #include <vnet/fib/fib_entry_src.h>
18 : #include <vnet/fib/fib_node_list.h>
19 : #include <vnet/fib/fib_entry_delegate.h>
20 :
21 : u32
22 18948 : fib_entry_cover_track (fib_entry_t* cover,
23 : fib_node_index_t covered)
24 : {
25 : fib_entry_delegate_t *fed;
26 :
27 18948 : FIB_ENTRY_DBG(cover, "cover-track %d", covered);
28 :
29 18948 : ASSERT(fib_entry_get_index(cover) != covered);
30 :
31 18948 : fed = fib_entry_delegate_find(cover, FIB_ENTRY_DELEGATE_COVERED);
32 :
33 18948 : if (NULL == fed)
34 : {
35 7656 : fed = fib_entry_delegate_find_or_add(cover, FIB_ENTRY_DELEGATE_COVERED);
36 7656 : fed->fd_list = fib_node_list_create();
37 : }
38 :
39 18948 : return (fib_node_list_push_front(fed->fd_list,
40 : 0, FIB_NODE_TYPE_ENTRY,
41 : covered));
42 : }
43 :
44 : void
45 14567 : fib_entry_cover_untrack (fib_entry_t* cover,
46 : u32 tracked_index)
47 : {
48 : fib_entry_delegate_t *fed;
49 :
50 14567 : FIB_ENTRY_DBG(cover, "cover-untrack @ %d", tracked_index);
51 :
52 14567 : fed = fib_entry_delegate_find(cover, FIB_ENTRY_DELEGATE_COVERED);
53 :
54 14567 : if (NULL == fed)
55 0 : return;
56 :
57 14567 : fib_node_list_remove(fed->fd_list, tracked_index);
58 :
59 14567 : if (0 == fib_node_list_get_size(fed->fd_list))
60 : {
61 7250 : fib_node_list_destroy(&fed->fd_list);
62 7250 : fib_entry_delegate_remove(cover, FIB_ENTRY_DELEGATE_COVERED);
63 : }
64 : }
65 :
66 : /**
67 : * Internal struct to hold user supplied parameters for the cover walk
68 : */
69 : typedef struct fib_enty_cover_walk_ctx_t_ {
70 : fib_entry_t *cover;
71 : fib_entry_covered_walk_t walk;
72 : void *ctx;
73 : } fib_enty_cover_walk_ctx_t;
74 :
75 : static walk_rc_t
76 5539 : fib_entry_cover_walk_node_ptr (fib_node_ptr_t *depend,
77 : void *args)
78 : {
79 5539 : fib_enty_cover_walk_ctx_t *ctx = args;
80 :
81 5539 : ctx->walk(ctx->cover, depend->fnp_index, ctx->ctx);
82 :
83 5539 : return (WALK_CONTINUE);
84 : }
85 :
86 : void
87 53088 : fib_entry_cover_walk (fib_entry_t *cover,
88 : fib_entry_covered_walk_t walk,
89 : void *args)
90 : {
91 : fib_entry_delegate_t *fed;
92 :
93 53088 : fed = fib_entry_delegate_find(cover, FIB_ENTRY_DELEGATE_COVERED);
94 :
95 53088 : if (NULL == fed)
96 49111 : return;
97 :
98 3977 : fib_enty_cover_walk_ctx_t ctx = {
99 : .cover = cover,
100 : .walk = walk,
101 : .ctx = args,
102 : };
103 :
104 3977 : fib_node_list_walk(fed->fd_list,
105 : fib_entry_cover_walk_node_ptr,
106 : &ctx);
107 : }
108 :
109 : static walk_rc_t
110 4375 : fib_entry_cover_change_one (fib_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 4375 : new_cover = pointer_to_uword(args);
125 :
126 4375 : 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 4087 : fib_entry_cover_changed(covered);
133 : }
134 288 : else if (new_cover != covered)
135 : {
136 : const fib_prefix_t *pfx_covered, *pfx_new_cover;
137 :
138 288 : pfx_covered = fib_entry_get_prefix(covered);
139 288 : pfx_new_cover = fib_entry_get_prefix(new_cover);
140 :
141 288 : if (fib_prefix_is_cover(pfx_new_cover, pfx_covered))
142 : {
143 153 : fib_entry_cover_changed(covered);
144 : }
145 : }
146 4375 : return (WALK_CONTINUE);
147 : }
148 :
149 : void
150 40293 : fib_entry_cover_change_notify (fib_node_index_t cover_index,
151 : fib_node_index_t covered)
152 : {
153 : fib_entry_t *cover;
154 :
155 40293 : cover = fib_entry_get(cover_index);
156 :
157 40293 : fib_entry_cover_walk(cover,
158 : fib_entry_cover_change_one,
159 40293 : uword_to_pointer(covered, void*));
160 40293 : }
161 :
162 : static walk_rc_t
163 14 : fib_entry_cover_update_one (fib_entry_t *cover,
164 : fib_node_index_t covered,
165 : void *args)
166 : {
167 14 : fib_entry_cover_updated(covered);
168 :
169 14 : return (WALK_CONTINUE);
170 : }
171 :
172 : void
173 4213 : fib_entry_cover_update_notify (fib_entry_t *fib_entry)
174 : {
175 4213 : fib_entry_cover_walk(fib_entry,
176 : fib_entry_cover_update_one,
177 : NULL);
178 4213 : }
|