blob: 47bc5c30ce6834cd7bafe1eff189e28064ae4fc3 [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>
Neale Ranns1f50bf82019-07-16 15:28:52 +000019#include <vnet/fib/fib_entry_delegate.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010020
21u32
22fib_entry_cover_track (fib_entry_t* cover,
23 fib_node_index_t covered)
24{
Neale Rannsad422ed2016-11-02 14:20:04 +000025 fib_entry_delegate_t *fed;
26
Neale Ranns0bfe5d82016-08-25 15:29:12 +010027 FIB_ENTRY_DBG(cover, "cover-track %d", covered);
28
29 ASSERT(fib_entry_get_index(cover) != covered);
30
Neale Ranns1f50bf82019-07-16 15:28:52 +000031 fed = fib_entry_delegate_find(cover, FIB_ENTRY_DELEGATE_COVERED);
Neale Rannsad422ed2016-11-02 14:20:04 +000032
33 if (NULL == fed)
Neale Ranns0bfe5d82016-08-25 15:29:12 +010034 {
Neale Rannsad422ed2016-11-02 14:20:04 +000035 fed = fib_entry_delegate_find_or_add(cover, FIB_ENTRY_DELEGATE_COVERED);
36 fed->fd_list = fib_node_list_create();
Neale Ranns0bfe5d82016-08-25 15:29:12 +010037 }
38
Neale Rannsad422ed2016-11-02 14:20:04 +000039 return (fib_node_list_push_front(fed->fd_list,
Neale Ranns0bfe5d82016-08-25 15:29:12 +010040 0, FIB_NODE_TYPE_ENTRY,
41 covered));
42}
43
44void
45fib_entry_cover_untrack (fib_entry_t* cover,
46 u32 tracked_index)
47{
Neale Rannsad422ed2016-11-02 14:20:04 +000048 fib_entry_delegate_t *fed;
49
Neale Ranns0bfe5d82016-08-25 15:29:12 +010050 FIB_ENTRY_DBG(cover, "cover-untrack @ %d", tracked_index);
51
Neale Ranns1f50bf82019-07-16 15:28:52 +000052 fed = fib_entry_delegate_find(cover, FIB_ENTRY_DELEGATE_COVERED);
Neale Rannsad422ed2016-11-02 14:20:04 +000053
54 if (NULL == fed)
Neale Ranns0bfe5d82016-08-25 15:29:12 +010055 return;
56
Neale Rannsad422ed2016-11-02 14:20:04 +000057 fib_node_list_remove(fed->fd_list, tracked_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +010058
Neale Rannsad422ed2016-11-02 14:20:04 +000059 if (0 == fib_node_list_get_size(fed->fd_list))
Neale Ranns0bfe5d82016-08-25 15:29:12 +010060 {
Neale Rannsad422ed2016-11-02 14:20:04 +000061 fib_node_list_destroy(&fed->fd_list);
62 fib_entry_delegate_remove(cover, FIB_ENTRY_DELEGATE_COVERED);
Neale Ranns0bfe5d82016-08-25 15:29:12 +010063 }
64}
65
66/**
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -070067 * Internal struct to hold user supplied parameters for the cover walk
Neale Ranns0bfe5d82016-08-25 15:29:12 +010068 */
69typedef 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
Neale Rannsfdf6b6f2020-11-26 09:34:39 +000075static walk_rc_t
Neale Ranns0bfe5d82016-08-25 15:29:12 +010076fib_entry_cover_walk_node_ptr (fib_node_ptr_t *depend,
77 void *args)
78{
79 fib_enty_cover_walk_ctx_t *ctx = args;
80
81 ctx->walk(ctx->cover, depend->fnp_index, ctx->ctx);
82
Neale Rannsfdf6b6f2020-11-26 09:34:39 +000083 return (WALK_CONTINUE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +010084}
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 Ranns1f50bf82019-07-16 15:28:52 +000093 fed = fib_entry_delegate_find(cover, FIB_ENTRY_DELEGATE_COVERED);
Neale Rannsad422ed2016-11-02 14:20:04 +000094
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 Rannsfdf6b6f2020-11-26 09:34:39 +0000109static walk_rc_t
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100110fib_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 {
Neale Rannsc5d43172018-07-30 08:04:40 -0700136 const fib_prefix_t *pfx_covered, *pfx_new_cover;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100137
Neale Rannsc5d43172018-07-30 08:04:40 -0700138 pfx_covered = fib_entry_get_prefix(covered);
139 pfx_new_cover = fib_entry_get_prefix(new_cover);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100140
Neale Rannsc5d43172018-07-30 08:04:40 -0700141 if (fib_prefix_is_cover(pfx_new_cover, pfx_covered))
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100142 {
143 fib_entry_cover_changed(covered);
144 }
145 }
Neale Rannsfdf6b6f2020-11-26 09:34:39 +0000146 return (WALK_CONTINUE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100147}
148
149void
150fib_entry_cover_change_notify (fib_node_index_t cover_index,
151 fib_node_index_t covered)
152{
153 fib_entry_t *cover;
154
155 cover = fib_entry_get(cover_index);
156
157 fib_entry_cover_walk(cover,
158 fib_entry_cover_change_one,
159 uword_to_pointer(covered, void*));
160}
161
Neale Rannsfdf6b6f2020-11-26 09:34:39 +0000162static walk_rc_t
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100163fib_entry_cover_update_one (fib_entry_t *cover,
164 fib_node_index_t covered,
165 void *args)
166{
167 fib_entry_cover_updated(covered);
168
Neale Rannsfdf6b6f2020-11-26 09:34:39 +0000169 return (WALK_CONTINUE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100170}
171
172void
173fib_entry_cover_update_notify (fib_entry_t *fib_entry)
174{
175 fib_entry_cover_walk(fib_entry,
176 fib_entry_cover_update_one,
177 NULL);
178}