4 * Copyright (c) 2013 Cisco and/or its affiliates.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include <vnet/vnet.h>
19 #include <vnet/plugin/plugin.h>
21 #include <vnet/gre/gre.h>
22 #include <vnet/vxlan/vxlan.h>
23 #include <vnet/vxlan-gpe/vxlan_gpe.h>
24 #include <vnet/l2/l2_classify.h>
25 #include <vnet/adj/adj.h>
26 #include <vpp/app/version.h>
30 /* Uses network order's class and type to register */
32 nsh_md2_register_option (u16 class,
35 int add_options (u8 * opt,
37 int options (vlib_buffer_t * b,
38 nsh_tlv_header_t * opt),
39 int swap_options (vlib_buffer_t * b,
40 nsh_tlv_header_t * old_opt,
41 nsh_tlv_header_t * new_opt),
42 int pop_options (vlib_buffer_t * b,
43 nsh_tlv_header_t * opt),
44 u8 * trace (u8 * s, nsh_tlv_header_t * opt))
46 nsh_main_t *nm = &nsh_main;
47 nsh_option_map_by_key_t key, *key_copy;
49 nsh_option_map_t *nsh_option;
55 p = hash_get_mem (nm->nsh_option_map_by_key, &key);
56 /* Already registered */
62 pool_get_aligned (nm->nsh_option_mappings, nsh_option,
63 CLIB_CACHE_LINE_BYTES);
64 clib_memset (nsh_option, 0, sizeof (*nsh_option));
65 nsh_option->option_id = nsh_option - nm->nsh_option_mappings;
67 key_copy = clib_mem_alloc (sizeof (*key_copy));
68 clib_memcpy (key_copy, &key, sizeof (*key_copy));
69 hash_set_mem (nm->nsh_option_map_by_key, key_copy,
70 nsh_option - nm->nsh_option_mappings);
72 if (option_size > (MAX_NSH_OPTION_LEN + sizeof (nsh_tlv_header_t)))
76 nm->options_size[nsh_option->option_id] = option_size;
77 nm->add_options[nsh_option->option_id] = add_options;
78 nm->options[nsh_option->option_id] = options;
79 nm->swap_options[nsh_option->option_id] = swap_options;
80 nm->pop_options[nsh_option->option_id] = pop_options;
81 nm->trace[nsh_option->option_id] = trace;
86 /* Uses network order's class and type to lookup */
88 nsh_md2_lookup_option (u16 class, u8 type)
90 nsh_main_t *nm = &nsh_main;
91 nsh_option_map_by_key_t key;
98 p = hash_get_mem (nm->nsh_option_map_by_key, &key);
105 return pool_elt_at_index (nm->nsh_option_mappings, p[0]);
109 /* Uses network order's class and type to unregister */
111 nsh_md2_unregister_option (u16 class,
113 int options (vlib_buffer_t * b,
114 nsh_tlv_header_t * opt),
115 u8 * trace (u8 * s, nsh_tlv_header_t * opt))
117 nsh_main_t *nm = &nsh_main;
118 nsh_option_map_by_key_t key, *key_copy;
121 nsh_option_map_t *nsh_option;
127 p = hash_get_mem (nm->nsh_option_map_by_key, &key);
134 nsh_option = pool_elt_at_index (nm->nsh_option_mappings, p[0]);
135 nm->options[nsh_option->option_id] = NULL;
136 nm->add_options[nsh_option->option_id] = NULL;
137 nm->pop_options[nsh_option->option_id] = NULL;
138 nm->trace[nsh_option->option_id] = NULL;
140 hp = hash_get_pair (nm->nsh_option_map_by_key, &key);
141 key_copy = (void *) (hp->key);
142 hash_unset_mem (nm->nsh_option_map_by_key, &key_copy);
143 clib_mem_free (key_copy);
145 pool_put (nm->nsh_option_mappings, nsh_option);
151 * @brief Naming for NSH tunnel
153 * @param *s formatting string
156 * @return *s formatted string
160 format_nsh_name (u8 * s, va_list * args)
162 u32 dev_instance = va_arg (*args, u32);
163 return format (s, "nsh_tunnel%d", dev_instance);
167 * @brief CLI function for NSH admin up/down
176 static clib_error_t *
177 nsh_interface_admin_up_down (vnet_main_t * vnm, u32 nsh_hw_if, u32 flags)
179 if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
180 vnet_hw_interface_set_flags (vnm, nsh_hw_if,
181 VNET_HW_INTERFACE_FLAG_LINK_UP);
183 vnet_hw_interface_set_flags (vnm, nsh_hw_if, 0);
189 dummy_interface_tx (vlib_main_t * vm,
190 vlib_node_runtime_t * node, vlib_frame_t * frame)
192 clib_warning ("you shouldn't be here, leaking buffers...");
193 return frame->n_vectors;
197 VNET_DEVICE_CLASS (nsh_device_class, static) = {
199 .format_device_name = format_nsh_name,
200 .tx_function = dummy_interface_tx,
201 .admin_up_down_function = nsh_interface_admin_up_down,
206 * @brief Formatting function for tracing VXLAN GPE with length
215 format_nsh_tunnel_with_length (u8 * s, va_list * args)
217 u32 dev_instance = va_arg (*args, u32);
218 s = format (s, "unimplemented dev %u", dev_instance);
223 VNET_HW_INTERFACE_CLASS (nsh_hw_class) = {
225 .format_header = format_nsh_tunnel_with_length,
226 .build_rewrite = default_build_rewrite,
227 .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
232 nsh_md2_set_next_ioam_export_override (uword next)
234 nsh_main_t *hm = &nsh_main;
235 hm->decap_v4_next_override = next;
240 nsh_init (vlib_main_t * vm)
243 nsh_main_t *nm = &nsh_main;
244 clib_error_t *error = 0;
247 /* Init the main structures from VPP */
249 nm->vnet_main = vnet_get_main ();
251 /* Various state maintenance mappings */
252 nm->nsh_mapping_by_key = hash_create_mem (0, sizeof (u32), sizeof (uword));
254 nm->nsh_mapping_by_mapped_key
255 = hash_create_mem (0, sizeof (u32), sizeof (uword));
257 nm->nsh_entry_by_key = hash_create_mem (0, sizeof (u32), sizeof (uword));
259 nm->nsh_proxy_session_by_key
261 hash_create_mem (0, sizeof (nsh_proxy_session_by_key_t), sizeof (uword));
263 nm->nsh_option_map_by_key
264 = hash_create_mem (0, sizeof (nsh_option_map_by_key_t), sizeof (uword));
266 error = nsh_api_init (vm, nm);
270 node = vlib_get_node_by_name (vm, (u8 *) "nsh-input");
271 nm->nsh_input_node_index = node->index;
273 node = vlib_get_node_by_name (vm, (u8 *) "nsh-proxy");
274 nm->nsh_proxy_node_index = node->index;
276 node = vlib_get_node_by_name (vm, (u8 *) "nsh-classifier");
277 nm->nsh_classifier_node_index = node->index;
279 /* Add dispositions to nodes that feed nsh-input */
280 //alagalah - validate we don't really need to use the node value
282 vlib_node_add_next (vm, vxlan4_gpe_input_node.index,
283 nm->nsh_input_node_index);
284 vlib_node_add_next (vm, vxlan4_gpe_input_node.index,
285 nm->nsh_proxy_node_index);
286 vlib_node_add_next (vm, vxlan4_gpe_input_node.index,
287 nsh_aware_vnf_proxy_node.index);
288 vxlan_gpe_register_decap_protocol (VXLAN_GPE_PROTOCOL_NSH, next_node);
290 vlib_node_add_next (vm, vxlan6_gpe_input_node.index,
291 nm->nsh_input_node_index);
292 vlib_node_add_next (vm, vxlan6_gpe_input_node.index,
293 nm->nsh_proxy_node_index);
294 vlib_node_add_next (vm, vxlan6_gpe_input_node.index,
295 nsh_aware_vnf_proxy_node.index);
297 vlib_node_add_next (vm, gre4_input_node.index, nm->nsh_input_node_index);
298 vlib_node_add_next (vm, gre4_input_node.index, nm->nsh_proxy_node_index);
299 vlib_node_add_next (vm, gre4_input_node.index,
300 nsh_aware_vnf_proxy_node.index);
302 vlib_node_add_next (vm, gre6_input_node.index, nm->nsh_input_node_index);
303 vlib_node_add_next (vm, gre6_input_node.index, nm->nsh_proxy_node_index);
304 vlib_node_add_next (vm, gre6_input_node.index,
305 nsh_aware_vnf_proxy_node.index);
307 /* Add NSH-Proxy support */
308 vlib_node_add_next (vm, vxlan4_input_node.index, nm->nsh_proxy_node_index);
309 vlib_node_add_next (vm, vxlan6_input_node.index, nm->nsh_proxy_node_index);
311 /* Add NSH-Classifier support */
312 vlib_node_add_next (vm, ip4_classify_node.index,
313 nm->nsh_classifier_node_index);
314 vlib_node_add_next (vm, ip6_classify_node.index,
315 nm->nsh_classifier_node_index);
316 vlib_node_add_next (vm, l2_input_classify_node.index,
317 nm->nsh_classifier_node_index);
319 /* Add Ethernet+NSH support */
320 ethernet_register_input_type (vm, ETHERNET_TYPE_NSH,
321 nm->nsh_input_node_index);
326 VLIB_INIT_FUNCTION (nsh_init);
329 VLIB_PLUGIN_REGISTER () = {
330 .version = VPP_BUILD_VER,
331 .description = "Network Service Header",
336 * fd.io coding-style-patch-verification: ON
339 * eval: (c-set-style "gnu")