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/adj/adj_delegate.h>
17 : #include <vnet/adj/adj_midchain.h>
18 : #include <vnet/fib/fib_table.h>
19 : #include <vnet/fib/fib_entry_track.h>
20 :
21 : /**
22 : * Midchain stacker delegate
23 : */
24 : typedef struct adj_midchain_delegate_t_
25 : {
26 : /**
27 : * the Fib Entry we are stacked on
28 : */
29 : fib_node_index_t amd_fei;
30 :
31 : /**
32 : * The sibling entry on the FIB entry
33 : */
34 : u32 amd_sibling;
35 : } adj_midchain_delegate_t;
36 :
37 : /**
38 : * Pool of delegates
39 : */
40 : static adj_midchain_delegate_t *amd_pool;
41 :
42 : static inline const adj_midchain_delegate_t*
43 2 : adj_midchain_from_const_base (const adj_delegate_t *ad)
44 : {
45 2 : if (NULL != ad)
46 : {
47 2 : return (pool_elt_at_index(amd_pool, ad->ad_index));
48 : }
49 0 : return (NULL);
50 : }
51 :
52 : static void
53 729 : adj_midchain_delegate_restack_i (adj_index_t ai,
54 : adj_midchain_delegate_t *amd)
55 : {
56 729 : if (vnet_sw_interface_is_admin_up (vnet_get_main (),
57 693 : adj_get_sw_if_index(ai)) &&
58 693 : (FIB_NODE_INDEX_INVALID != amd->amd_fei))
59 693 : {
60 : const fib_prefix_t *pfx;
61 :
62 693 : pfx = fib_entry_get_prefix(amd->amd_fei);
63 :
64 693 : adj_nbr_midchain_stack_on_fib_entry (
65 : ai,
66 : amd->amd_fei,
67 693 : fib_forw_chain_type_from_fib_proto(pfx->fp_proto));
68 : }
69 : else
70 : {
71 36 : adj_nbr_midchain_unstack (ai);
72 : }
73 729 : }
74 :
75 : void
76 263 : adj_midchain_delegate_restack (adj_index_t ai)
77 : {
78 : adj_midchain_delegate_t *amd;
79 : ip_adjacency_t *adj;
80 : adj_delegate_t *ad;
81 :
82 : /*
83 : * if there's a delegate already use that
84 : */
85 263 : adj = adj_get(ai);
86 263 : ad = adj_delegate_get(adj, ADJ_DELEGATE_MIDCHAIN);
87 :
88 263 : if (NULL != ad)
89 : {
90 263 : amd = pool_elt_at_index(amd_pool, ad->ad_index);
91 :
92 263 : adj_midchain_delegate_restack_i(ai, amd);
93 : }
94 : /*
95 : * else
96 : * nothing to stack
97 : */
98 263 : }
99 :
100 : void
101 466 : adj_midchain_delegate_stack (adj_index_t ai,
102 : u32 fib_index,
103 : const fib_prefix_t *pfx)
104 : {
105 : adj_midchain_delegate_t *amd;
106 : ip_adjacency_t *adj;
107 : adj_delegate_t *ad;
108 :
109 : /*
110 : * if there's a delegate already use that
111 : */
112 466 : adj = adj_get(ai);
113 466 : ad = adj_delegate_get(adj, ADJ_DELEGATE_MIDCHAIN);
114 :
115 466 : if (NULL != ad)
116 : {
117 87 : amd = pool_elt_at_index(amd_pool, ad->ad_index);
118 : }
119 : else
120 : {
121 379 : pool_get(amd_pool, amd);
122 379 : amd->amd_fei = FIB_NODE_INDEX_INVALID;
123 379 : adj_delegate_add(adj, ADJ_DELEGATE_MIDCHAIN, amd - amd_pool);
124 :
125 379 : amd->amd_fei = fib_entry_track(fib_index,
126 : pfx,
127 : FIB_NODE_TYPE_ADJ,
128 : ai,
129 379 : &amd->amd_sibling);
130 : }
131 466 : adj_midchain_delegate_restack_i(ai, amd);
132 466 : }
133 :
134 : void
135 8 : adj_midchain_delegate_remove (adj_index_t ai)
136 : {
137 : adj_midchain_delegate_t *amd;
138 : ip_adjacency_t *adj;
139 : adj_delegate_t *ad;
140 :
141 : /*
142 : * if there's a delegate, it can be removed
143 : */
144 8 : adj = adj_get(ai);
145 8 : ad = adj_delegate_get(adj, ADJ_DELEGATE_MIDCHAIN);
146 :
147 8 : if (NULL != ad)
148 : {
149 8 : adj_nbr_midchain_unstack(ai);
150 :
151 8 : amd = pool_elt_at_index(amd_pool, ad->ad_index);
152 8 : fib_entry_untrack(amd->amd_fei, amd->amd_sibling);
153 8 : pool_put(amd_pool, amd);
154 :
155 8 : adj_delegate_remove (ai, ADJ_DELEGATE_MIDCHAIN);
156 : }
157 8 : }
158 :
159 : void
160 343 : adj_midchain_delegate_unstack (adj_index_t ai)
161 : {
162 343 : adj_nbr_midchain_unstack(ai);
163 343 : }
164 :
165 : static void
166 369 : adj_midchain_delegate_adj_deleted (adj_delegate_t *ad)
167 : {
168 : adj_midchain_delegate_t *amd;
169 :
170 369 : amd = pool_elt_at_index(amd_pool, ad->ad_index);
171 :
172 369 : fib_entry_untrack(amd->amd_fei, amd->amd_sibling);
173 :
174 369 : pool_put(amd_pool, amd);
175 369 : }
176 :
177 : /**
178 : * Print a delegate that represents MIDCHAIN tracking
179 : */
180 : static u8 *
181 2 : adj_midchain_delegate_fmt (const adj_delegate_t *aed, u8 *s)
182 : {
183 2 : const adj_midchain_delegate_t *amd = adj_midchain_from_const_base(aed);
184 :
185 2 : s = format(s, "MIDCHAIN:[fib-entry:%d]", amd->amd_fei);
186 :
187 2 : return (s);
188 : }
189 :
190 : const static adj_delegate_vft_t adj_delegate_vft = {
191 : .adv_format = adj_midchain_delegate_fmt,
192 : .adv_adj_deleted = adj_midchain_delegate_adj_deleted,
193 : };
194 :
195 : static clib_error_t *
196 559 : adj_midchain_delegate_module_init (vlib_main_t * vm)
197 : {
198 559 : clib_error_t * error = NULL;
199 :
200 559 : adj_delegate_register_type (ADJ_DELEGATE_MIDCHAIN, &adj_delegate_vft);
201 :
202 559 : return (error);
203 : }
204 :
205 81759 : VLIB_INIT_FUNCTION (adj_midchain_delegate_module_init);
206 :
|