blob: 814df578a62c3b1540527e50f39955aaa50ebfbf [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
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100109static int
110fib_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 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 fib_entry_cover_changed(covered);
133 }
134 else if (new_cover != covered)
135 {
136 fib_prefix_t pfx_covered, pfx_new_cover;
137
138 fib_entry_get_prefix(covered, &pfx_covered);
139 fib_entry_get_prefix(new_cover, &pfx_new_cover);
140
141 if (fib_prefix_is_cover(&pfx_new_cover, &pfx_covered))
142 {
143 fib_entry_cover_changed(covered);
144 }
145 }
146 /* continue */
147 return (1);
148}
149
150void
151fib_entry_cover_change_notify (fib_node_index_t cover_index,
152 fib_node_index_t covered)
153{
154 fib_entry_t *cover;
155
156 cover = fib_entry_get(cover_index);
157
158 fib_entry_cover_walk(cover,
159 fib_entry_cover_change_one,
160 uword_to_pointer(covered, void*));
161}
162
163static int
164fib_entry_cover_update_one (fib_entry_t *cover,
165 fib_node_index_t covered,
166 void *args)
167{
168 fib_entry_cover_updated(covered);
169
170 /* continue */
171 return (1);
172}
173
174void
175fib_entry_cover_update_notify (fib_entry_t *fib_entry)
176{
177 fib_entry_cover_walk(fib_entry,
178 fib_entry_cover_update_one,
179 NULL);
180}