Line data Source code
1 : /*
2 : * Copyright (c) 2020 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 :
18 : #include <linux-cp/lcp_interface.h>
19 : #include <linux-cp/lcp_adj.h>
20 :
21 : #include <vppinfra/bihash_32_8.h>
22 : #include <vppinfra/bihash_template.c>
23 :
24 : static adj_delegate_type_t adj_type;
25 : static lcp_adj_key_t *adj_keys;
26 :
27 : /**
28 : * The table of adjacencies indexed by the rewrite string
29 : */
30 : BVT (clib_bihash) lcp_adj_tbl;
31 :
32 : static_always_inline void
33 4 : lcp_adj_mk_key_adj (const ip_adjacency_t *adj, lcp_adj_key_t *key)
34 : {
35 4 : lcp_adj_mk_key (adj->rewrite_header.data, adj->rewrite_header.data_bytes,
36 : adj->rewrite_header.sw_if_index, key);
37 4 : }
38 :
39 : static u8 *
40 0 : lcp_adj_delegate_format (const adj_delegate_t *aed, u8 *s)
41 : {
42 0 : return (format (s, "lcp"));
43 : }
44 :
45 : static void
46 4 : lcp_adj_delegate_adj_deleted (adj_delegate_t *aed)
47 : {
48 : ip_adjacency_t *adj;
49 : lcp_adj_kv_t kv;
50 :
51 4 : adj = adj_get (aed->ad_adj_index);
52 :
53 4 : lcp_adj_mk_key_adj (adj, &kv.k);
54 :
55 4 : BV (clib_bihash_add_del) (&lcp_adj_tbl, &kv.kv, 0);
56 :
57 4 : if (aed->ad_index != INDEX_INVALID)
58 0 : pool_put_index (adj_keys, aed->ad_index);
59 4 : }
60 :
61 : /* when an adj is modified:
62 : *
63 : * An existing hash entry may need to be deleted. This may occur when:
64 : * * The newly modified adj does not have IP_LOOKUP_NEXT_REWRITE as next idx
65 : * * The rewrite (== major component of hash key) changed
66 : *
67 : * A new hash entry may need to be added. This may occur when:
68 : * * The newly modified adj has IP_LOOKUP_NEXT_REWRITE as next idx
69 : * * The rewrite changed or there was no existing hash entry
70 : */
71 : static void
72 0 : lcp_adj_delegate_adj_modified (adj_delegate_t *aed)
73 : {
74 : ip_adjacency_t *adj;
75 : lcp_adj_kv_t kv;
76 0 : lcp_adj_key_t *adj_key = NULL;
77 : u8 save_adj, key_changed;
78 :
79 0 : key_changed = 0;
80 :
81 0 : adj = adj_get (aed->ad_adj_index);
82 0 : save_adj = (IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index);
83 :
84 0 : if (aed->ad_index != INDEX_INVALID)
85 0 : adj_key = pool_elt_at_index (adj_keys, aed->ad_index);
86 :
87 : /* return if there was no stored adj and we will not add one */
88 0 : if (!adj_key && !save_adj)
89 0 : return;
90 :
91 : /* build kv if a new entry should be stored */
92 0 : if (save_adj)
93 : {
94 0 : lcp_adj_mk_key_adj (adj, &kv.k);
95 0 : kv.v = aed->ad_adj_index;
96 0 : if (adj_key)
97 0 : key_changed = (clib_memcmp (adj_key, &kv.k, sizeof (*adj_key)) != 0);
98 : }
99 :
100 : /* delete old entry if needed */
101 0 : if (adj_key && ((save_adj && key_changed) || (!save_adj)))
102 : {
103 : lcp_adj_kv_t old_kv;
104 :
105 0 : clib_memcpy_fast (&old_kv.k, adj_key, sizeof (*adj_key));
106 0 : old_kv.v = 0;
107 :
108 0 : BV (clib_bihash_add_del) (&lcp_adj_tbl, &old_kv.kv, 0);
109 :
110 0 : if (!save_adj)
111 : {
112 0 : pool_put (adj_keys, adj_key);
113 0 : aed->ad_index = INDEX_INVALID;
114 : }
115 : }
116 :
117 : /* add new entry if needed */
118 0 : if (save_adj)
119 : {
120 0 : BV (clib_bihash_add_del) (&lcp_adj_tbl, &kv.kv, 1);
121 :
122 0 : if (!adj_key)
123 : {
124 0 : pool_get (adj_keys, adj_key);
125 0 : aed->ad_index = adj_key - adj_keys;
126 : }
127 0 : clib_memcpy_fast (adj_key, &kv.k, sizeof (*adj_key));
128 : }
129 : }
130 :
131 : static void
132 78 : lcp_adj_delegate_adj_created (adj_index_t ai)
133 : {
134 : ip_adjacency_t *adj;
135 : lcp_adj_kv_t kv;
136 78 : index_t lai = INDEX_INVALID;
137 : lcp_adj_key_t *adj_key;
138 : index_t lipi;
139 : lcp_itf_pair_t *lip;
140 :
141 78 : adj = adj_get (ai);
142 :
143 78 : lipi = lcp_itf_pair_find_by_phy (adj->rewrite_header.sw_if_index);
144 78 : if (lipi == INDEX_INVALID)
145 74 : return;
146 :
147 6 : lip = lcp_itf_pair_get (lipi);
148 6 : if (lip->lip_host_type == LCP_ITF_HOST_TUN)
149 2 : return;
150 :
151 4 : if (IP_LOOKUP_NEXT_REWRITE == adj->lookup_next_index)
152 : {
153 0 : lcp_adj_mk_key_adj (adj, &kv.k);
154 0 : pool_get (adj_keys, adj_key);
155 0 : clib_memcpy_fast (adj_key, &kv.k, sizeof (*adj_key));
156 0 : kv.v = ai;
157 :
158 0 : BV (clib_bihash_add_del) (&lcp_adj_tbl, &kv.kv, 1);
159 0 : lai = adj_key - adj_keys;
160 : }
161 :
162 4 : adj_delegate_add (adj, adj_type, lai);
163 : }
164 :
165 : u8 *
166 0 : format_lcp_adj_kvp (u8 *s, va_list *args)
167 : {
168 0 : BVT (clib_bihash_kv) *kv = va_arg (*args, BVT (clib_bihash_kv) *);
169 0 : CLIB_UNUSED (int verbose) = va_arg (*args, int);
170 0 : lcp_adj_kv_t *akv = (lcp_adj_kv_t *) kv;
171 :
172 0 : s = format (s, " %U:%U\n %U", format_vnet_sw_if_index_name,
173 : vnet_get_main (), akv->k.sw_if_index, format_hex_bytes,
174 0 : akv->k.rewrite, 18, format_adj_nbr, akv->v, 4);
175 :
176 0 : return (s);
177 : }
178 :
179 : static clib_error_t *
180 2 : lcp_adj_show_cmd (vlib_main_t *vm, unformat_input_t *input,
181 : vlib_cli_command_t *cmd)
182 : {
183 2 : u8 verbose = 0;
184 :
185 2 : if (unformat (input, "verbose"))
186 2 : verbose = 1;
187 :
188 2 : vlib_cli_output (vm, "linux-cp adjacencies:\n%U", BV (format_bihash),
189 : &lcp_adj_tbl, verbose);
190 :
191 2 : return 0;
192 : }
193 :
194 588 : VLIB_CLI_COMMAND (lcp_itf_pair_show_cmd_node, static) = {
195 : .path = "show lcp adj",
196 : .function = lcp_adj_show_cmd,
197 : .short_help = "show lcp adj",
198 : .is_mp_safe = 1,
199 : };
200 :
201 : const adj_delegate_vft_t lcp_adj_vft = {
202 : .adv_format = lcp_adj_delegate_format,
203 : .adv_adj_deleted = lcp_adj_delegate_adj_deleted,
204 : .adv_adj_modified = lcp_adj_delegate_adj_modified,
205 : .adv_adj_created = lcp_adj_delegate_adj_created,
206 : };
207 :
208 : static clib_error_t *
209 2 : lcp_adj_init (vlib_main_t *vm)
210 : {
211 2 : adj_type = adj_delegate_register_new_type (&lcp_adj_vft);
212 :
213 2 : BV (clib_bihash_init) (&lcp_adj_tbl, "linux-cp adjacencies", 1024, 1 << 24);
214 2 : BV (clib_bihash_set_kvp_format_fn) (&lcp_adj_tbl, format_lcp_adj_kvp);
215 :
216 2 : return (NULL);
217 : }
218 :
219 6 : VLIB_INIT_FUNCTION (lcp_adj_init);
220 :
221 : /*
222 : * fd.io coding-style-patch-verification: ON
223 : *
224 : * Local Variables:
225 : * eval: (c-set-style "gnu")
226 : * End:
227 : */
|