FD.io VPP  v19.04.4-rc0-5-ge88582fac
Vector Packet Processing
nsh_api.c
Go to the documentation of this file.
1 /*
2  * nsh_api.c - nsh mapping api
3  *
4  * Copyright (c) 2019 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:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17 #include <vnet/vnet.h>
18 #include <vnet/plugin/plugin.h>
19 #include <nsh/nsh.h>
20 
21 #include <vlibapi/api.h>
22 #include <vlibmemory/api.h>
23 #include <vpp/app/version.h>
24 
25 /* define message IDs */
26 #define vl_msg_id(n,h) n,
27 typedef enum
28 {
29 #include <nsh/nsh.api.h>
30  /* We'll want to know how many messages IDs we need... */
32 } vl_msg_id_t;
33 #undef vl_msg_id
34 
35 /* define message structures */
36 #define vl_typedefs
37 #include <nsh/nsh.api.h>
38 #undef vl_typedefs
39 
40 /* define generated endian-swappers */
41 #define vl_endianfun
42 #include <nsh/nsh.api.h>
43 #undef vl_endianfun
44 
45 /* instantiate all the print functions we know about */
46 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
47 #define vl_printfun
48 #include <nsh/nsh.api.h>
49 #undef vl_printfun
50 
51 /* Get the API version number */
52 #define vl_api_version(n,v) static u32 api_version=(v);
53 #include <nsh/nsh.api.h>
54 #undef vl_api_version
55 
56 #define vl_msg_name_crc_list
57 #include <nsh/nsh.api.h>
58 #undef vl_msg_name_crc_list
59 
60 #define REPLY_MSG_ID_BASE nm->msg_id_base
62 
63 /* List of message types that this plugin understands */
64 
65 #define foreach_nsh_plugin_api_msg \
66  _(NSH_ADD_DEL_ENTRY, nsh_add_del_entry) \
67  _(NSH_ENTRY_DUMP, nsh_entry_dump) \
68  _(NSH_ADD_DEL_MAP, nsh_add_del_map) \
69  _(NSH_MAP_DUMP, nsh_map_dump)
70 
71 /**
72  * @brief CLI function for NSH admin up/down
73  *
74  * @param *vnm
75  * @param nsh_hw_if
76  * @param flag
77  *
78  * @return *rc
79  *
80  */
81 static clib_error_t *
83 {
85  vnet_hw_interface_set_flags (vnm, nsh_hw_if,
87  else
88  vnet_hw_interface_set_flags (vnm, nsh_hw_if, 0);
89 
90  return 0;
91 }
92 
93 static uword
95  vlib_node_runtime_t * node, vlib_frame_t * frame)
96 {
97  clib_warning ("you shouldn't be here, leaking buffers...");
98  return frame->n_vectors;
99 }
100 
101 /**
102  * @brief Naming for NSH tunnel
103  *
104  * @param *s formatting string
105  * @param *args
106  *
107  * @return *s formatted string
108  *
109  */
110 static u8 *
111 format_nsh_name (u8 * s, va_list * args)
112 {
113  u32 dev_instance = va_arg (*args, u32);
114  return format (s, "nsh_tunnel%d", dev_instance);
115 }
116 
117 /* *INDENT-OFF* */
118 VNET_DEVICE_CLASS (nsh_device_class, static) = {
119  .name = "NSH",
120  .format_device_name = format_nsh_name,
121  .tx_function = dummy_interface_tx,
122  .admin_up_down_function = nsh_interface_admin_up_down,
123 };
124 /* *INDENT-ON* */
125 
126 static void send_nsh_entry_details
127  (nsh_entry_t * t, vl_api_registration_t * rp, u32 context)
128 {
130  nsh_main_t *nm = &nsh_main;
131 
132  rmp = vl_msg_api_alloc (sizeof (*rmp));
133  clib_memset (rmp, 0, sizeof (*rmp));
134 
135  rmp->_vl_msg_id = ntohs ((VL_API_NSH_ENTRY_DETAILS) + nm->msg_id_base);
136  rmp->ver_o_c = t->nsh_base.ver_o_c;
137  rmp->ttl = (t->nsh_base.ver_o_c & NSH_TTL_H4_MASK) << 2 |
138  (t->nsh_base.length & NSH_TTL_L2_MASK) >> 6;
139  rmp->length = t->nsh_base.length & NSH_LEN_MASK;
140  rmp->md_type = t->nsh_base.md_type;
141  rmp->next_protocol = t->nsh_base.next_protocol;
142  rmp->nsp_nsi = htonl (t->nsh_base.nsp_nsi);
143 
144  if (t->nsh_base.md_type == 1)
145  {
146  rmp->tlv_length = 4;
147  rmp->c1 = htonl (t->md.md1_data.c1);
148  rmp->c2 = htonl (t->md.md1_data.c2);
149  rmp->c3 = htonl (t->md.md1_data.c3);
150  rmp->c4 = htonl (t->md.md1_data.c4);
151  }
152  else if (t->nsh_base.md_type == 2)
153  {
154  rmp->tlv_length = t->tlvs_len;
155  clib_memcpy (rmp->tlv, t->tlvs_data, t->tlvs_len);
156  }
157 
158  rmp->context = context;
159 
160  vl_api_send_msg (rp, (u8 *) rmp);
161 }
162 
163 static void send_nsh_map_details
164  (nsh_map_t * t, vl_api_registration_t * rp, u32 context)
165 {
167  nsh_main_t *nm = &nsh_main;
168 
169  rmp = vl_msg_api_alloc (sizeof (*rmp));
170  clib_memset (rmp, 0, sizeof (*rmp));
171 
172  rmp->_vl_msg_id = ntohs ((VL_API_NSH_MAP_DETAILS) + nm->msg_id_base);
173  rmp->nsp_nsi = htonl (t->nsp_nsi);
174  rmp->mapped_nsp_nsi = htonl (t->mapped_nsp_nsi);
175  rmp->nsh_action = htonl (t->nsh_action);
176  rmp->sw_if_index = htonl (t->sw_if_index);
177  rmp->rx_sw_if_index = htonl (t->rx_sw_if_index);
178  rmp->next_node = htonl (t->next_node);
179 
180  rmp->context = context;
181 
182  vl_api_send_msg (rp, (u8 *) rmp);
183 }
184 
185 static void
187 {
188  nsh_main_t *nm = &nsh_main;
189  nsh_map_t *t;
190  u32 map_index;
192 
194  if (rp == 0)
195  return;
196 
197  map_index = ntohl (mp->map_index);
198 
199  if (~0 == map_index)
200  {
201  pool_foreach (t, nm->nsh_mappings, (
202  {
203  send_nsh_map_details (t, rp,
204  mp->context);
205  }
206  ));
207  }
208  else
209  {
210  if (map_index >= vec_len (nm->nsh_mappings))
211  {
212  return;
213  }
214  t = &nm->nsh_mappings[map_index];
215  send_nsh_map_details (t, rp, mp->context);
216  }
217 }
218 
219 /** API message handler */
220 static void
222 {
224  nsh_main_t *nm = &nsh_main;
225  int rv;
226  nsh_add_del_map_args_t _a, *a = &_a;
227  u32 map_index = ~0;
228 
229  a->is_add = mp->is_add;
230  a->map.nsp_nsi = ntohl (mp->nsp_nsi);
231  a->map.mapped_nsp_nsi = ntohl (mp->mapped_nsp_nsi);
232  a->map.nsh_action = ntohl (mp->nsh_action);
233  a->map.sw_if_index = ntohl (mp->sw_if_index);
234  a->map.rx_sw_if_index = ntohl (mp->rx_sw_if_index);
235  a->map.next_node = ntohl (mp->next_node);
236 
237  rv = nsh_add_del_map (a, &map_index);
238 
239  if ((a->map.next_node == NSH_NODE_NEXT_ENCAP_VXLAN4)
240  | (a->map.next_node == NSH_NODE_NEXT_ENCAP_VXLAN6))
241  {
242  rv = nsh_add_del_proxy_session (a);
243  }
244 
245  REPLY_MACRO2 (VL_API_NSH_ADD_DEL_MAP_REPLY, (
246  {
247  rmp->map_index =
248  htonl (map_index);
249  }
250  ));
251 }
252 
253 int
255 {
256  u8 *rw = 0;
257  int len = 0;
258  nsh_base_header_t *nsh_base;
259  nsh_md1_data_t *nsh_md1;
260  nsh_main_t *nm = &nsh_main;
261  nsh_md2_data_t *opt0;
262  nsh_md2_data_t *limit0;
263  nsh_md2_data_t *nsh_md2;
264  nsh_option_map_t _nsh_option, *nsh_option = &_nsh_option;
265  u8 old_option_size = 0;
266  u8 new_option_size = 0;
267 
268  vec_free (nsh_entry->rewrite);
269  if (nsh_entry->nsh_base.md_type == 1)
270  {
271  len = sizeof (nsh_base_header_t) + sizeof (nsh_md1_data_t);
272  }
273  else if (nsh_entry->nsh_base.md_type == 2)
274  {
275  /* set to maxim, maybe dataplane will add more TLVs */
276  len = MAX_NSH_HEADER_LEN;
277  }
279  clib_memset (rw, 0, len);
280 
281  nsh_base = (nsh_base_header_t *) rw;
282  nsh_base->ver_o_c = nsh_entry->nsh_base.ver_o_c;
283  nsh_base->length = nsh_entry->nsh_base.length;
284  nsh_base->md_type = nsh_entry->nsh_base.md_type;
285  nsh_base->next_protocol = nsh_entry->nsh_base.next_protocol;
286  nsh_base->nsp_nsi = clib_host_to_net_u32 (nsh_entry->nsh_base.nsp_nsi);
287 
288  if (nsh_base->md_type == 1)
289  {
290  nsh_md1 = (nsh_md1_data_t *) (rw + sizeof (nsh_base_header_t));
291  nsh_md1->c1 = clib_host_to_net_u32 (nsh_entry->md.md1_data.c1);
292  nsh_md1->c2 = clib_host_to_net_u32 (nsh_entry->md.md1_data.c2);
293  nsh_md1->c3 = clib_host_to_net_u32 (nsh_entry->md.md1_data.c3);
294  nsh_md1->c4 = clib_host_to_net_u32 (nsh_entry->md.md1_data.c4);
295  nsh_entry->rewrite_size = 24;
296  }
297  else if (nsh_base->md_type == 2)
298  {
299  opt0 = (nsh_md2_data_t *) (nsh_entry->tlvs_data);
300  limit0 = (nsh_md2_data_t *) ((u8 *) opt0 + nsh_entry->tlvs_len);
301 
302  nsh_md2 = (nsh_md2_data_t *) (rw + sizeof (nsh_base_header_t));
303  nsh_entry->rewrite_size = sizeof (nsh_base_header_t);
304 
305  while (opt0 < limit0)
306  {
307  old_option_size = sizeof (nsh_md2_data_t) + opt0->length;
308  /* round to 4-byte */
309  old_option_size = ((old_option_size + 3) >> 2) << 2;
310 
311  nsh_option = nsh_md2_lookup_option (opt0->class, opt0->type);
312  if (nsh_option == NULL)
313  {
314  goto next_tlv_md2;
315  }
316 
317  if (nm->add_options[nsh_option->option_id] != NULL)
318  {
319  if (0 != nm->add_options[nsh_option->option_id] ((u8 *) nsh_md2,
320  &new_option_size))
321  {
322  goto next_tlv_md2;
323  }
324 
325  /* round to 4-byte */
326  new_option_size = ((new_option_size + 3) >> 2) << 2;
327 
328  nsh_entry->rewrite_size += new_option_size;
329  nsh_md2 =
330  (nsh_md2_data_t *) (((u8 *) nsh_md2) + new_option_size);
331  opt0 = (nsh_md2_data_t *) (((u8 *) opt0) + old_option_size);
332  }
333  else
334  {
335  next_tlv_md2:
336  opt0 = (nsh_md2_data_t *) (((u8 *) opt0) + old_option_size);
337  }
338 
339  }
340  }
341 
342  nsh_entry->rewrite = rw;
343  nsh_base->length = (nsh_base->length & NSH_TTL_L2_MASK) |
344  ((nsh_entry->rewrite_size >> 2) & NSH_LEN_MASK);
345 
346  return 0;
347 }
348 
350 
351 /**
352  * Action function to add or del an nsh map.
353  * Shared by both CLI and binary API
354  **/
355 int
357 {
358  nsh_main_t *nm = &nsh_main;
359  vnet_main_t *vnm = nm->vnet_main;
360  nsh_map_t *map = 0;
361  u32 key, *key_copy;
362  uword *entry;
363  hash_pair_t *hp;
364  u32 map_index = ~0;
366  u32 nsh_hw_if = ~0;
367  u32 nsh_sw_if = ~0;
368 
369  /* net order, so data plane could use nsh header to lookup directly */
370  key = clib_host_to_net_u32 (a->map.nsp_nsi);
371 
372  entry = hash_get_mem (nm->nsh_mapping_by_key, &key);
373 
374  if (a->is_add)
375  {
376  /* adding an entry, must not already exist */
377  if (entry)
378  return -1; //TODO API_ERROR_INVALID_VALUE;
379 
381  clib_memset (map, 0, sizeof (*map));
382 
383  /* copy from arg structure */
384  map->nsp_nsi = a->map.nsp_nsi;
386  map->nsh_action = a->map.nsh_action;
387  map->sw_if_index = a->map.sw_if_index;
389  map->next_node = a->map.next_node;
390  map->adj_index = a->map.adj_index;
391 
392 
393  key_copy = clib_mem_alloc (sizeof (*key_copy));
394  clib_memcpy (key_copy, &key, sizeof (*key_copy));
395 
396  hash_set_mem (nm->nsh_mapping_by_key, key_copy, map - nm->nsh_mappings);
397  map_index = map - nm->nsh_mappings;
398 
400  {
401  nsh_hw_if = nm->free_nsh_tunnel_hw_if_indices
403  _vec_len (nm->free_nsh_tunnel_hw_if_indices) -= 1;
404 
405  hi = vnet_get_hw_interface (vnm, nsh_hw_if);
406  hi->dev_instance = map_index;
407  hi->hw_instance = hi->dev_instance;
408  }
409  else
410  {
411  nsh_hw_if = vnet_register_interface
412  (vnm, nsh_device_class.index, map_index, nsh_hw_class.index,
413  map_index);
414  hi = vnet_get_hw_interface (vnm, nsh_hw_if);
416  }
417 
418  map->nsh_hw_if = nsh_hw_if;
419  map->nsh_sw_if = nsh_sw_if = hi->sw_if_index;
421  ~0);
422  nm->tunnel_index_by_sw_if_index[nsh_sw_if] = key;
423 
426  }
427  else
428  {
429  if (!entry)
430  return -2; //TODO API_ERROR_NO_SUCH_ENTRY;
431 
432  map = pool_elt_at_index (nm->nsh_mappings, entry[0]);
433 
437  nm->tunnel_index_by_sw_if_index[map->nsh_sw_if] = ~0;
438 
439  hp = hash_get_pair (nm->nsh_mapping_by_key, &key);
440  key_copy = (void *) (hp->key);
442  clib_mem_free (key_copy);
443 
444  pool_put (nm->nsh_mappings, map);
445  }
446 
447  if (map_indexp)
448  *map_indexp = map_index;
449 
450  return 0;
451 }
452 
453 /**
454  * Action function to add or del an nsh-proxy-session.
455  * Shared by both CLI and binary API
456  **/
457 int
459 {
460  nsh_main_t *nm = &nsh_main;
461  nsh_proxy_session_t *proxy = 0;
462  nsh_proxy_session_by_key_t key, *key_copy;
463  uword *entry;
464  hash_pair_t *hp;
465  u32 nsp = 0, nsi = 0;
466 
467  clib_memset (&key, 0, sizeof (key));
468  key.transport_type = a->map.next_node;
470 
471  entry = hash_get_mem (nm->nsh_proxy_session_by_key, &key);
472 
473  if (a->is_add)
474  {
475  /* adding an entry, must not already exist */
476  if (entry)
477  return -1; //TODO API_ERROR_INVALID_VALUE;
478 
480  clib_memset (proxy, 0, sizeof (*proxy));
481 
482  /* Nsi needs to minus 1 within NSH-Proxy */
483  nsp = (a->map.nsp_nsi >> NSH_NSP_SHIFT) & NSH_NSP_MASK;
484  nsi = a->map.nsp_nsi & NSH_NSI_MASK;
485  if (nsi == 0)
486  return -1;
487 
488  nsi = nsi - 1;
489  /* net order, so could use it to lookup nsh map table directly */
490  proxy->nsp_nsi = clib_host_to_net_u32 ((nsp << NSH_NSP_SHIFT) | nsi);
491 
492  key_copy = clib_mem_alloc (sizeof (*key_copy));
493  clib_memcpy (key_copy, &key, sizeof (*key_copy));
494 
495  hash_set_mem (nm->nsh_proxy_session_by_key, key_copy,
496  proxy - nm->nsh_proxy_sessions);
497  }
498  else
499  {
500  if (!entry)
501  return -2; //TODO API_ERROR_NO_SUCH_ENTRY;
502 
503  proxy = pool_elt_at_index (nm->nsh_proxy_sessions, entry[0]);
504  hp = hash_get_pair (nm->nsh_proxy_session_by_key, &key);
505  key_copy = (void *) (hp->key);
507  clib_mem_free (key_copy);
508 
509  pool_put (nm->nsh_proxy_sessions, proxy);
510  }
511 
512  return 0;
513 }
514 
515 /**
516  * Action function for adding an NSH entry
517  * nsh_add_del_entry_args_t *a: host order
518  */
519 int
521 {
522  nsh_main_t *nm = &nsh_main;
523  nsh_entry_t *nsh_entry = 0;
524  u32 key, *key_copy;
525  uword *entry_id;
526  hash_pair_t *hp;
527  u32 entry_index = ~0;
528  u8 tlvs_len = 0;
529  u8 *data = 0;
530 
531  /* host order, because nsh map table stores nsp_nsi in host order */
532  key = a->nsh_entry.nsh_base.nsp_nsi;
533 
534  entry_id = hash_get_mem (nm->nsh_entry_by_key, &key);
535 
536  if (a->is_add)
537  {
538  /* adding an entry, must not already exist */
539  if (entry_id)
540  return -1; // TODO VNET_API_ERROR_INVALID_VALUE;
541 
543  clib_memset (nsh_entry, 0, sizeof (*nsh_entry));
544 
545  /* copy from arg structure */
546 #define _(x) nsh_entry->nsh_base.x = a->nsh_entry.nsh_base.x;
548 #undef _
549 
550  if (a->nsh_entry.nsh_base.md_type == 1)
551  {
552  nsh_entry->md.md1_data.c1 = a->nsh_entry.md.md1_data.c1;
553  nsh_entry->md.md1_data.c2 = a->nsh_entry.md.md1_data.c2;
554  nsh_entry->md.md1_data.c3 = a->nsh_entry.md.md1_data.c3;
555  nsh_entry->md.md1_data.c4 = a->nsh_entry.md.md1_data.c4;
556  }
557  else if (a->nsh_entry.nsh_base.md_type == 2)
558  {
559  vec_free (nsh_entry->tlvs_data);
560  tlvs_len = a->nsh_entry.tlvs_len;
561  vec_validate_aligned (data, tlvs_len - 1, CLIB_CACHE_LINE_BYTES);
562 
563  clib_memcpy (data, a->nsh_entry.tlvs_data, tlvs_len);
564  nsh_entry->tlvs_data = data;
565  nsh_entry->tlvs_len = tlvs_len;
567  }
568 
569  nsh_header_rewrite (nsh_entry);
570 
571  key_copy = clib_mem_alloc (sizeof (*key_copy));
572  clib_memcpy (key_copy, &key, sizeof (*key_copy));
573 
574  hash_set_mem (nm->nsh_entry_by_key, key_copy,
575  nsh_entry - nm->nsh_entries);
576  entry_index = nsh_entry - nm->nsh_entries;
577  }
578  else
579  {
580  if (!entry_id)
581  return -2; //TODO API_ERROR_NO_SUCH_ENTRY;
582 
583  nsh_entry = pool_elt_at_index (nm->nsh_entries, entry_id[0]);
584  hp = hash_get_pair (nm->nsh_entry_by_key, &key);
585  key_copy = (void *) (hp->key);
586  hash_unset_mem (nm->nsh_entry_by_key, &key);
587  clib_mem_free (key_copy);
588 
589  vec_free (nsh_entry->tlvs_data);
590  vec_free (nsh_entry->rewrite);
591  pool_put (nm->nsh_entries, nsh_entry);
592  }
593 
594  if (entry_indexp)
595  *entry_indexp = entry_index;
596 
597  return 0;
598 }
599 
600 
601 /** API message handler */
604 {
606  nsh_main_t *nm = &nsh_main;
607  int rv;
608  nsh_add_del_entry_args_t _a, *a = &_a;
609  u32 entry_index = ~0;
610  u8 tlvs_len = 0;
611  u8 *data = 0;
612 
613  a->is_add = mp->is_add;
614  a->nsh_entry.nsh_base.ver_o_c =
615  (mp->ver_o_c & 0xF0) | ((mp->ttl & NSH_LEN_MASK) >> 2);
616  a->nsh_entry.nsh_base.length =
617  (mp->length & NSH_LEN_MASK) | ((mp->ttl & 0x3) << 6);
618  a->nsh_entry.nsh_base.md_type = mp->md_type;
619  a->nsh_entry.nsh_base.next_protocol = mp->next_protocol;
620  a->nsh_entry.nsh_base.nsp_nsi = ntohl (mp->nsp_nsi);
621  if (mp->md_type == 1)
622  {
623  a->nsh_entry.md.md1_data.c1 = ntohl (mp->c1);
624  a->nsh_entry.md.md1_data.c2 = ntohl (mp->c2);
625  a->nsh_entry.md.md1_data.c3 = ntohl (mp->c3);
626  a->nsh_entry.md.md1_data.c4 = ntohl (mp->c4);
627  }
628  else if (mp->md_type == 2)
629  {
630  tlvs_len = mp->tlv_length;
631  vec_validate_aligned (data, tlvs_len - 1, CLIB_CACHE_LINE_BYTES);
632 
633  clib_memcpy (data, mp->tlv, tlvs_len);
634  a->nsh_entry.tlvs_data = data;
635  a->nsh_entry.tlvs_len = tlvs_len;
636  }
637 
638  rv = nsh_add_del_entry (a, &entry_index);
639 
640  REPLY_MACRO2 (VL_API_NSH_ADD_DEL_ENTRY_REPLY, (
641  {
642  rmp->entry_index =
643  htonl (entry_index);
644  }
645  ));
646 }
647 
648 static void
650 {
651  nsh_main_t *nm = &nsh_main;
652  nsh_entry_t *t;
653  u32 entry_index;
655 
657  if (rp == 0)
658  return;
659 
660  entry_index = ntohl (mp->entry_index);
661 
662  if (~0 == entry_index)
663  {
664  pool_foreach (t, nm->nsh_entries, (
665  {
666  send_nsh_entry_details (t, rp,
667  mp->context);
668  }
669  ));
670  }
671  else
672  {
673  if (entry_index >= vec_len (nm->nsh_entries))
674  {
675  return;
676  }
677  t = &nm->nsh_entries[entry_index];
678  send_nsh_entry_details (t, rp, mp->context);
679  }
680 }
681 
682 static void
684 {
685 #define _(id,n,crc) \
686  vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + nm->msg_id_base);
687  foreach_vl_msg_name_crc_nsh;
688 #undef _
689 }
690 
691 /* Set up the API message handling tables */
692 static clib_error_t *
694 {
695  nsh_main_t *nm __attribute__ ((unused)) = &nsh_main;
696 #define _(N,n) \
697  vl_msg_api_set_handlers((VL_API_##N + nm->msg_id_base), \
698  #n, \
699  vl_api_##n##_t_handler, \
700  vl_noop_handler, \
701  vl_api_##n##_t_endian, \
702  vl_api_##n##_t_print, \
703  sizeof(vl_api_##n##_t), 1);
705 #undef _
706 
707  return 0;
708 }
709 
710 clib_error_t *
712 {
713  clib_error_t *error;
714  u8 *name;
715 
716  name = format (0, "nsh_%08x%c", api_version, 0);
717 
718  /* Set up the API */
720  ((char *) name, VL_MSG_FIRST_AVAILABLE);
721 
722  error = nsh_plugin_api_hookup (vm);
723 
724  /* Add our API messages to the global name_crc hash table */
726 
727  vec_free (name);
728 
729  return error;
730 }
731 
732 /*
733  * fd.io coding-style-patch-verification: ON
734  *
735  * Local Variables:
736  * eval: (c-set-style "gnu")
737  * End:
738  */
VNET_DEVICE_CLASS(nsh_device_class, static)
u32 entry_index
Definition: nsh.api:44
u32 sw_if_index
Definition: nsh.h:82
vmrglw vmrglh hi
u32 nsh_action
Definition: nsh.h:74
#define VNET_SW_INTERFACE_FLAG_ADMIN_DOWN
Definition: nsh.h:241
static uword dummy_interface_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: nsh_api.c:94
Reply from adding NSH entry (nsh_add_del_entry)
Definition: nsh.api:41
u32 flags
Definition: vhost_user.h:115
#define NSH_NSP_MASK
Definition: nsh_packet.h:113
u32 * tunnel_index_by_sw_if_index
Mapping from sw_if_index to tunnel index.
Definition: nsh.h:131
u8 tlv[248]
Definition: nsh.api:34
a
Definition: bitmap.h:538
u32 c4
Definition: nsh.api:32
#define REPLY_MACRO2(t, body)
#define NULL
Definition: clib.h:58
u32 c1
Definition: nsh.api:63
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 next_node
Definition: nsh.h:84
static void vl_api_send_msg(vl_api_registration_t *rp, u8 *elem)
Definition: api.h:34
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
u8 ver_o_c
Definition: nsh.api:25
u32 nsh_sw_if
Definition: nsh.h:79
#define NSH_LEN_MASK
Definition: nsh_packet.h:109
union nsh_entry_t::@555 md
#define hash_set_mem(h, key, value)
Definition: hash.h:275
static void send_nsh_map_details(nsh_map_t *t, vl_api_registration_t *rp, u32 context)
Definition: nsh_api.c:164
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
u8 data[128]
Definition: ipsec.api:248
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:450
u32 nsp_nsi
Definition: nsh.api:23
int nsh_add_del_proxy_session(nsh_add_del_map_args_t *a)
Action function to add or del an nsh-proxy-session.
Definition: nsh_api.c:458
vlib_node_registration_t nsh_aware_vnf_proxy_node
(constructor) VLIB_REGISTER_NODE (nsh_aware_vnf_proxy_node)
Definition: nsh_node.c:959
u32 context
Definition: nsh.api:50
void * vl_msg_api_alloc(int nbytes)
u32 c1
Definition: nsh.api:29
unsigned char u8
Definition: types.h:56
u8 tlv[248]
Definition: nsh.api:68
nsh_base_header_t nsh_base
Definition: nsh.h:40
u32 c2
Definition: nsh.api:30
/**
Definition: nsh.api:19
nsh_proxy_session_t * nsh_proxy_sessions
Definition: nsh.h:123
u32 client_index
Definition: nsh.api:49
#define clib_memcpy(d, s, n)
Definition: string.h:180
u8 length
Definition: nsh.api:61
u32 context
Definition: nsh.api:55
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:493
int(* add_options[MAX_MD2_OPTIONS])(u8 *opt, u8 *opt_size)
Definition: nsh.h:146
u8 is_add
Definition: nsh.h:55
u8 next_protocol
Definition: nsh.api:28
#define foreach_copy_nsh_base_hdr_field
Definition: nsh.h:183
nsh_entry_t * nsh_entries
Definition: nsh.h:110
vl_msg_id_t
Definition: nsh_api.c:27
u32 adj_index
Definition: nsh.h:85
#define hash_get_pair(h, key)
Definition: hash.h:252
unsigned int u32
Definition: types.h:88
u32 * free_nsh_tunnel_hw_if_indices
Free vlib hw_if_indices.
Definition: nsh.h:129
u32 vnet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u32 hw_class_index, u32 hw_instance)
Definition: interface.c:740
u16 msg_id_base
Definition: nsh.h:107
nsh_option_map_t * nsh_md2_lookup_option(u16 class, u8 type)
Definition: nsh.c:88
u32 c3
Definition: nsh.api:31
u32 c2
Definition: nsh.api:64
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
#define hash_unset_mem(h, key)
Definition: hash.h:291
Definition: nsh.h:59
static void vl_api_nsh_add_del_entry_t_handler(vl_api_nsh_add_del_entry_t *mp)
API message handler.
Definition: nsh_api.c:603
nsh_map_t * nsh_mappings
Definition: nsh.h:116
uword * nsh_entry_by_key
Definition: nsh.h:113
u8 * rewrite
Rewrite string.
Definition: nsh.h:50
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
u8 tlv_length
Definition: nsh.api:67
int nsh_add_del_map(nsh_add_del_map_args_t *a, u32 *map_indexp)
Action function to add or del an nsh map.
Definition: nsh_api.c:356
u32 c4
Definition: nsh.api:66
u8 name[64]
Definition: memclnt.api:152
static u8 * format_nsh_name(u8 *s, va_list *args)
Naming for NSH tunnel.
Definition: nsh_api.c:111
u8 len
Definition: ip_types.api:49
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:202
Definition: nsh.h:54
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P with alignment A.
Definition: pool.h:230
An API client registration, only in vpp/vlib.
Definition: api_common.h:45
static void setup_message_id_table(nsh_main_t *nm, api_main_t *am)
Definition: nsh_api.c:683
static void vl_api_nsh_map_dump_t_handler(vl_api_nsh_map_dump_t *mp)
Definition: nsh_api.c:186
u16 n_vectors
Definition: node.h:395
vlib_main_t * vm
Definition: buffer.c:312
u8 md_type
Definition: nsh.api:24
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
u8 length
Definition: nsh.api:27
#define MAX_NSH_HEADER_LEN
Definition: nsh.h:250
u32 context
Definition: ipsec_gre.api:33
#define clib_warning(format, args...)
Definition: error.h:59
uword * nsh_proxy_session_by_key
Definition: nsh.h:126
u32 nsp_nsi
Key for nsh_header_t entry: 24bit NSP 8bit NSI.
Definition: nsh.h:64
#define NSH_NSI_MASK
Definition: nsh_packet.h:112
nsh_main_t nsh_main
Definition: nsh.c:28
u32 nsh_hw_if
vnet intfc hw_if_index
Definition: nsh.h:77
u8 tlvs_len
Definition: nsh.h:45
static vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
Definition: api.h:56
static clib_error_t * nsh_plugin_api_hookup(vlib_main_t *vm)
Definition: nsh_api.c:693
u32 nsp_nsi
Definition: nsh.api:57
nsh_tlv_header_t nsh_md2_data_t
Definition: nsh_packet.h:93
u32 mapped_nsp_nsi
Key for nsh_header_t entry to map to.
Definition: nsh.h:72
u8 next_protocol
Definition: nsh.api:62
u32 rx_sw_if_index
Definition: nsh.h:83
u32 option_id
Definition: nsh.h:29
nsh_map_t map
Definition: nsh.h:90
vnet_hw_interface_class_t nsh_hw_class
int nsh_add_del_entry(nsh_add_del_entry_args_t *a, u32 *entry_indexp)
Action function for adding an NSH entry nsh_add_del_entry_args_t *a: host order.
Definition: nsh_api.c:520
static void clib_mem_free(void *p)
Definition: mem.h:205
Set or delete a mapping from one NSH header to another and its egress (decap to inner packet...
Definition: nsh.api:86
nsh_md1_data_t md1_data
Definition: nsh.h:42
static clib_error_t * nsh_interface_admin_up_down(vnet_main_t *vnm, u32 nsh_hw_if, u32 flags)
CLI function for NSH admin up/down.
Definition: nsh_api.c:82
Definition: nsh.api:48
u8 ver_o_c
Definition: nsh.api:59
u8 ttl
Definition: nsh.api:60
static void vl_api_nsh_entry_dump_t_handler(vl_api_nsh_entry_dump_t *mp)
Definition: nsh_api.c:649
static void send_nsh_entry_details(nsh_entry_t *t, vl_api_registration_t *rp, u32 context)
Definition: nsh_api.c:127
static void * clib_mem_alloc(uword size)
Definition: mem.h:132
u8 rewrite_size
Definition: nsh.h:51
u8 is_add
Definition: nsh.api:22
u8 tlv_length
Definition: nsh.api:33
u8 * tlvs_data
Definition: nsh.h:46
struct _vnet_hw_interface_class vnet_hw_interface_class_t
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: nsh.api:54
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
Definition: interface.c:504
u64 uword
Definition: types.h:112
u8 md_type
Definition: nsh.api:58
#define NSH_NSP_SHIFT
Definition: nsh_packet.h:114
typedef key
Definition: ipsec.api:244
u32 c3
Definition: nsh.api:65
vnet_main_t * vnet_main
Definition: nsh.h:168
#define NSH_TTL_L2_MASK
Definition: nsh_packet.h:108
#define hash_get_mem(h, key)
Definition: hash.h:269
Reply from adding NSH map (nsh_add_del_map)
Definition: nsh.api:102
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, vnet_sw_interface_flags_t flags)
Definition: interface.c:513
u8 ttl
Definition: nsh.api:26
Note: rewrite and rewrite_size used to support varied nsh header.
Definition: nsh.h:36
clib_error_t * nsh_api_init(vlib_main_t *vm, nsh_main_t *nm)
Definition: nsh_api.c:711
#define NSH_TTL_H4_MASK
Definition: nsh_packet.h:107
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:486
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static void vl_api_nsh_add_del_map_t_handler(vl_api_nsh_add_del_map_t *mp)
API message handler.
Definition: nsh_api.c:221
u32 entry_index
Definition: nsh.api:51
api_main_t api_main
Definition: api_shared.c:35
uword * nsh_mapping_by_key
Definition: nsh.h:119
int nsh_header_rewrite(nsh_entry_t *nsh_entry)
Definition: nsh_api.c:254
#define foreach_nsh_plugin_api_msg
Definition: nsh_api.c:65
uword key
Definition: hash.h:162
nsh_entry_t nsh_entry
Definition: nsh.h:56
u16 vl_msg_api_get_msg_ids(const char *name, int n)
Definition: api_shared.c:880