FD.io VPP  v16.06
Vector Packet Processing
tapcli.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * tapcli.c - dynamic tap interface hookup
4  *
5  * Copyright (c) 2009 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19 
20 #include <fcntl.h> /* for open */
21 #include <sys/ioctl.h>
22 #include <sys/socket.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <sys/uio.h> /* for iovec */
26 #include <netinet/in.h>
27 
28 #include <linux/if_arp.h>
29 #include <linux/if_tun.h>
30 
31 #include <vlib/vlib.h>
32 #include <vlib/unix/unix.h>
33 
34 #include <vnet/ip/ip.h>
35 
36 #include <vnet/ethernet/ethernet.h>
37 
38 #if DPDK == 1
39 #include <vnet/devices/dpdk/dpdk.h>
40 #endif
41 
42 #include <vnet/unix/tapcli.h>
43 
47 
48 static void tapcli_nopunt_frame (vlib_main_t * vm,
49  vlib_node_runtime_t * node,
50  vlib_frame_t * frame);
51 typedef struct {
55  u32 sw_if_index; /* for counters */
58  struct ifreq ifr;
60  u8 active; /* for delete */
62 
63 typedef struct {
66 
67 u8 * format_tapcli_rx_trace (u8 * s, va_list * va)
68 {
69  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
70  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
71  vnet_main_t * vnm = vnet_get_main();
72  tapcli_rx_trace_t * t = va_arg (*va, tapcli_rx_trace_t *);
74  vnm, t->sw_if_index);
75  return s;
76 }
77 
78 typedef struct {
79  /* Vector of iovecs for readv/writev calls. */
80  struct iovec * iovecs;
81 
82  /* Vector of VLIB rx buffers to use. We allocate them in blocks
83  of VLIB_FRAME_SIZE (256). */
85 
86  /* tap device destination MAC address. Required, or Linux drops pkts */
87  u8 ether_dst_mac[6];
88 
89  /* Interface MTU in bytes and # of default sized buffers. */
90  u32 mtu_bytes, mtu_buffers;
91 
92  /* Vector of tap interfaces */
94 
95  /* Vector of deleted tap interfaces */
97 
98  /* Bitmap of tap interfaces with pending reads */
100 
101  /* Hash table to find tapcli interface given hw_if_index */
103 
104  /* Hash table to find tapcli interface given unix fd */
106 
107  /* renumbering table */
109 
110  /* 1 => disable CLI */
112 
113  /* convenience */
117 } tapcli_main_t;
118 
120 
121 /*
122  * tapcli_tx
123  * Output node, writes the buffers comprising the incoming frame
124  * to the tun/tap device, aka hands them to the Linux kernel stack.
125  *
126  */
127 static uword
129  vlib_node_runtime_t * node,
130  vlib_frame_t * frame)
131 {
132  u32 * buffers = vlib_frame_args (frame);
133  uword n_packets = frame->n_vectors;
134  tapcli_main_t * tm = &tapcli_main;
135  tapcli_interface_t * ti;
136  int i;
137 
138  for (i = 0; i < n_packets; i++)
139  {
140  struct iovec * iov;
141  vlib_buffer_t * b;
142  uword l;
143  vnet_hw_interface_t * hw;
144  uword * p;
145  u32 tx_sw_if_index;
146 
147  b = vlib_get_buffer (vm, buffers[i]);
148 
149  tx_sw_if_index = vnet_buffer(b)->sw_if_index[VLIB_TX];
150  if (tx_sw_if_index == (u32)~0)
151  tx_sw_if_index = vnet_buffer(b)->sw_if_index[VLIB_RX];
152 
153  ASSERT(tx_sw_if_index != (u32)~0);
154 
155  /* Use the sup intfc to finesse vlan subifs */
156  hw = vnet_get_sup_hw_interface (tm->vnet_main, tx_sw_if_index);
157  tx_sw_if_index = hw->sw_if_index;
158 
160  tx_sw_if_index);
161  if (p == 0)
162  {
163  clib_warning ("sw_if_index %d unknown", tx_sw_if_index);
164  /* $$$ leak, but this should never happen... */
165  continue;
166  }
167  else
168  ti = vec_elt_at_index (tm->tapcli_interfaces, p[0]);
169 
170  /* Re-set iovecs if present. */
171  if (tm->iovecs)
172  _vec_len (tm->iovecs) = 0;
173 
174  /* VLIB buffer chain -> Unix iovec(s). */
175  vec_add2 (tm->iovecs, iov, 1);
176  iov->iov_base = b->data + b->current_data;
177  iov->iov_len = l = b->current_length;
178 
180  {
181  do {
182  b = vlib_get_buffer (vm, b->next_buffer);
183 
184  vec_add2 (tm->iovecs, iov, 1);
185 
186  iov->iov_base = b->data + b->current_data;
187  iov->iov_len = b->current_length;
188  l += b->current_length;
189  } while (b->flags & VLIB_BUFFER_NEXT_PRESENT);
190  }
191 
192  if (writev (ti->unix_fd, tm->iovecs, vec_len (tm->iovecs)) < l)
193  clib_unix_warning ("writev");
194  }
195 
197 
198  return n_packets;
199 }
200 
202  .function = tapcli_tx,
203  .name = "tapcli-tx",
204  .type = VLIB_NODE_TYPE_INTERNAL,
205  .vector_size = 4,
206 };
207 
208 enum {
214 };
215 
216 
217 
219  vlib_node_runtime_t * node,
220  tapcli_interface_t * ti)
221 {
222  tapcli_main_t * tm = &tapcli_main;
223  const uword buffer_size = VLIB_BUFFER_DATA_SIZE;
224  u32 n_trace = vlib_get_trace_count (vm, node);
225  u8 set_trace = 0;
226 
227  vnet_main_t *vnm;
228  vnet_sw_interface_t * si;
229  u8 admin_down;
230  u32 next = node->cached_next_index;
231  u32 n_left_to_next, next_index;
232  u32 *to_next;
233 
234  vnm = vnet_get_main();
235  si = vnet_get_sw_interface (vnm, ti->sw_if_index);
236  admin_down = !(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP);
237 
238  vlib_get_next_frame(vm, node, next, to_next, n_left_to_next);
239 
240  while (n_left_to_next) { // Fill at most one vector
241  vlib_buffer_t *b_first, *b, *prev;
242  u32 bi_first, bi;
243  word n_bytes_in_packet;
244  int j, n_bytes_left;
245 
246  if (PREDICT_FALSE(vec_len(tm->rx_buffers) < tm->mtu_buffers)) {
247  uword len = vec_len(tm->rx_buffers);
248  _vec_len(tm->rx_buffers) +=
251  if (PREDICT_FALSE(vec_len(tm->rx_buffers) < tm->mtu_buffers)) {
252  clib_warning("vlib_buffer_alloc failed");
253  break;
254  }
255  }
256 
257  uword i_rx = vec_len (tm->rx_buffers) - 1;
258 
259  /* Allocate RX buffers from end of rx_buffers.
260  Turn them into iovecs to pass to readv. */
261  vec_validate (tm->iovecs, tm->mtu_buffers - 1);
262  for (j = 0; j < tm->mtu_buffers; j++) {
263  b = vlib_get_buffer (vm, tm->rx_buffers[i_rx - j]);
264  b->clone_count = 0;
265  tm->iovecs[j].iov_base = b->data;
266  tm->iovecs[j].iov_len = buffer_size;
267  }
268 
269  n_bytes_left = readv (ti->unix_fd, tm->iovecs, tm->mtu_buffers);
270  n_bytes_in_packet = n_bytes_left;
271  if (n_bytes_left <= 0) {
272  if (errno != EAGAIN) {
274  TAPCLI_ERROR_READ, 1);
275  }
276  break;
277  }
278 
279  bi_first = tm->rx_buffers[i_rx];
280  b = b_first = vlib_get_buffer (vm, tm->rx_buffers[i_rx]);
281  prev = NULL;
282 
283  while (1) {
284  b->current_length = n_bytes_left < buffer_size ? n_bytes_left : buffer_size;
285  n_bytes_left -= buffer_size;
286 
287  if (prev) {
288  prev->next_buffer = bi;
290  }
291  prev = b;
292 
293  /* last segment */
294  if (n_bytes_left <= 0)
295  break;
296 
297  i_rx--;
298  bi = tm->rx_buffers[i_rx];
299  b = vlib_get_buffer (vm, bi);
300  }
301 
302  _vec_len (tm->rx_buffers) = i_rx;
303 
305  (n_bytes_in_packet > buffer_size) ? n_bytes_in_packet - buffer_size : 0;
307 
308  /* Ensure mbufs are updated */
309  vlib_buffer_chain_validate(vm, b_first);
310 
312 
313  vnet_buffer (b_first)->sw_if_index[VLIB_RX] = ti->sw_if_index;
314  vnet_buffer (b_first)->sw_if_index[VLIB_TX] = (u32)~0;
315 
316  b_first->error = node->errors[TAPCLI_ERROR_NONE];
317  next_index = TAPCLI_RX_NEXT_ETHERNET_INPUT;
318  next_index = (ti->per_interface_next_index != ~0) ?
319  ti->per_interface_next_index : next_index;
320  next_index = admin_down ? TAPCLI_RX_NEXT_DROP : next_index;
321 
322  to_next[0] = bi_first;
323  to_next++;
324  n_left_to_next--;
325 
326  vlib_validate_buffer_enqueue_x1 (vm, node, next,
327  to_next, n_left_to_next,
328  bi_first, next_index);
329 
330  /* Interface counters for tapcli interface. */
331  if (PREDICT_TRUE(!admin_down)) {
336  1, n_bytes_in_packet);
337 
338  if (PREDICT_FALSE(n_trace > 0)) {
339  vlib_trace_buffer (vm, node, next_index,
340  b_first, /* follow_chain */ 1);
341  n_trace--;
342  set_trace = 1;
343  tapcli_rx_trace_t *t0 = vlib_add_trace (vm, node, b_first, sizeof (*t0));
344  t0->sw_if_index = si->sw_if_index;
345  }
346  }
347  }
348  vlib_put_next_frame (vm, node, next, n_left_to_next);
349  if (set_trace)
350  vlib_set_trace_count (vm, node, n_trace);
351  return VLIB_FRAME_SIZE - n_left_to_next;
352 }
353 
354 static uword
356  vlib_node_runtime_t * node,
357  vlib_frame_t * frame)
358 {
359  tapcli_main_t * tm = &tapcli_main;
360  static u32 * ready_interface_indices;
361  tapcli_interface_t * ti;
362  int i;
363  u32 total_count = 0;
364 
365  vec_reset_length (ready_interface_indices);
367  ({
368  vec_add1 (ready_interface_indices, i);
369  }));
370 
371  if (vec_len (ready_interface_indices) == 0)
372  return 1;
373 
374  for (i = 0; i < vec_len(ready_interface_indices); i++)
375  {
376  tm->pending_read_bitmap =
378  ready_interface_indices[i], 0);
379 
380  ti = vec_elt_at_index (tm->tapcli_interfaces, ready_interface_indices[i]);
381  total_count += tapcli_rx_iface(vm, node, ti);
382  }
383  return total_count; //This might return more than 256.
384 }
385 
386 static char * tapcli_rx_error_strings[] = {
387 #define _(sym,string) string,
389 #undef _
390 };
391 
393  .function = tapcli_rx,
394  .name = "tapcli-rx",
395  .type = VLIB_NODE_TYPE_INPUT,
396  .state = VLIB_NODE_STATE_INTERRUPT,
397  .vector_size = 4,
398  .n_errors = TAPCLI_N_ERROR,
399  .error_strings = tapcli_rx_error_strings,
400  .format_trace = format_tapcli_rx_trace,
401 
402  .n_next_nodes = TAPCLI_RX_N_NEXT,
403  .next_nodes = {
404  [TAPCLI_RX_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
405  [TAPCLI_RX_NEXT_IP6_INPUT] = "ip6-input",
406  [TAPCLI_RX_NEXT_DROP] = "error-drop",
407  [TAPCLI_RX_NEXT_ETHERNET_INPUT] = "ethernet-input",
408  },
409 };
410 
411 /* Gets called when file descriptor is ready from epoll. */
413 {
414  vlib_main_t * vm = vlib_get_main();
415  tapcli_main_t * tm = &tapcli_main;
416  uword * p;
417 
418  /* Schedule the rx node */
420 
422 
423  /* Mark the specific tap interface ready-to-read */
424  if (p)
426  p[0], 1);
427  else
428  clib_warning ("fd %d not in hash table", uf->file_descriptor);
429 
430  return 0;
431 }
432 
433 static clib_error_t *
435 {
436  tapcli_main_t *tm = &tapcli_main;
437  const uword buffer_size = VLIB_BUFFER_DATA_SIZE;
438 
440  {
441  if (unformat (input, "mtu %d", &tm->mtu_bytes))
442  ;
443  else if (unformat (input, "disable"))
444  tm->is_disabled = 1;
445  else
446  return clib_error_return (0, "unknown input `%U'",
447  format_unformat_error, input);
448  }
449 
450  if (tm->is_disabled)
451  return 0;
452 
453  if (geteuid())
454  {
455  clib_warning ("tapcli disabled: must be superuser");
456  tm->is_disabled = 1;
457  return 0;
458  }
459 
460  tm->mtu_buffers = (tm->mtu_bytes + (buffer_size - 1)) / buffer_size;
461 
462  return 0;
463 }
464 
466  u32 new_dev_instance)
467 {
468  tapcli_main_t *tm = &tapcli_main;
469 
471  hi->dev_instance, ~0);
472 
474  new_dev_instance;
475 
476  return 0;
477 }
478 
480 
481 static void
483  vlib_node_runtime_t * node,
484  vlib_frame_t * frame)
485 {
486  u32 * buffers = vlib_frame_args (frame);
487  uword n_packets = frame->n_vectors;
488  vlib_buffer_free (vm, buffers, n_packets);
489  vlib_frame_free (vm, node, frame);
490 }
491 
493  .name = "tapcli",
494 };
495 
496 static u8 * format_tapcli_interface_name (u8 * s, va_list * args)
497 {
498  u32 i = va_arg (*args, u32);
499  u32 show_dev_instance = ~0;
500  tapcli_main_t * tm = &tapcli_main;
501 
503  show_dev_instance = tm->show_dev_instance_by_real_dev_instance[i];
504 
505  if (show_dev_instance != ~0)
506  i = show_dev_instance;
507 
508  s = format (s, "tap-%d", i);
509  return s;
510 }
511 
513  vnet_hw_interface_t * hw,
514  u32 flags)
515 {
516  tapcli_main_t *tm = &tapcli_main;
517  tapcli_interface_t *ti;
518 
520 
521  if (flags & ETHERNET_INTERFACE_FLAG_MTU)
522  {
523  const uword buffer_size = VLIB_BUFFER_DATA_SIZE;
524  tm->mtu_bytes = hw->max_packet_bytes;
525  tm->mtu_buffers = (tm->mtu_bytes + (buffer_size - 1)) / buffer_size;
526  }
527  else
528  {
529  struct ifreq ifr;
530  u32 want_promisc;
531 
532  memcpy (&ifr, &ti->ifr, sizeof (ifr));
533 
534  /* get flags, modify to bring up interface... */
535  if (ioctl (ti->provision_fd, SIOCGIFFLAGS, &ifr) < 0)
536  {
537  clib_unix_warning ("Couldn't get interface flags for %s", hw->name);
538  return 0;
539  }
540 
541  want_promisc = (flags & ETHERNET_INTERFACE_FLAG_ACCEPT_ALL) != 0;
542 
543  if (want_promisc == ti->is_promisc)
544  return 0;
545 
547  ifr.ifr_flags |= IFF_PROMISC;
548  else
549  ifr.ifr_flags &= ~(IFF_PROMISC);
550 
551  /* get flags, modify to bring up interface... */
552  if (ioctl (ti->provision_fd, SIOCSIFFLAGS, &ifr) < 0)
553  {
554  clib_unix_warning ("Couldn't set interface flags for %s", hw->name);
555  return 0;
556  }
557 
558  ti->is_promisc = want_promisc;
559  }
560 
561  return 0;
562 }
563 
565  u32 hw_if_index,
566  u32 node_index)
567 {
568  tapcli_main_t *tm = &tapcli_main;
569  tapcli_interface_t *ti;
570  vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
571 
573 
574  /* Shut off redirection */
575  if (node_index == ~0)
576  {
577  ti->per_interface_next_index = node_index;
578  return;
579  }
580 
582  vlib_node_add_next (tm->vlib_main, tapcli_rx_node.index, node_index);
583 }
584 
585 /*
586  * Mainly exists to set link_state == admin_state
587  * otherwise, e.g. ip6 neighbor discovery breaks
588  */
589 static clib_error_t *
591 {
592  uword is_admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
593  u32 hw_flags;
596 
597  if (is_admin_up)
598  hw_flags = VNET_HW_INTERFACE_FLAG_LINK_UP | speed_duplex;
599  else
600  hw_flags = speed_duplex;
601 
602  vnet_hw_interface_set_flags (vnm, hw_if_index, hw_flags);
603  return 0;
604 }
605 
607  .name = "tapcli",
608  .tx_function = tapcli_tx,
609  .format_device_name = format_tapcli_interface_name,
610  .rx_redirect_to_node = tapcli_set_interface_next_node,
611  .name_renumber = tap_name_renumber,
612  .admin_up_down_function = tapcli_interface_admin_up_down,
613  .no_flatten_output_chains = 1,
614 };
615 
617 {
618  tapcli_main_t * tm = &tapcli_main;
619  tapcli_interface_t * ti;
620 
621  tapcli_interface_details_t * r_tapids = NULL;
623 
624  vec_foreach (ti, tm->tapcli_interfaces) {
625  if (!ti->active)
626  continue;
627  vec_add2(r_tapids, tapid, 1);
628  tapid->sw_if_index = ti->sw_if_index;
629  strncpy((char *)tapid->dev_name, ti->ifr.ifr_name, sizeof (ti->ifr.ifr_name)-1);
630  }
631 
632  *out_tapids = r_tapids;
633 
634  return 0;
635 }
636 
637 /* get tap interface from inactive interfaces or create new */
639 {
640  tapcli_main_t * tm = &tapcli_main;
641  tapcli_interface_t *ti = NULL;
642 
643  int inactive_cnt = vec_len(tm->tapcli_inactive_interfaces);
644  // if there are any inactive ifaces
645  if (inactive_cnt > 0) {
646  // take last
647  u32 ti_idx = tm->tapcli_inactive_interfaces[inactive_cnt - 1];
648  if (vec_len(tm->tapcli_interfaces) > ti_idx) {
649  ti = vec_elt_at_index (tm->tapcli_interfaces, ti_idx);
650  clib_warning("reusing tap interface");
651  }
652  // "remove" from inactive list
653  _vec_len(tm->tapcli_inactive_interfaces) -= 1;
654  }
655 
656  // ti was not retrieved from inactive ifaces - create new
657  if (!ti)
658  vec_add2 (tm->tapcli_interfaces, ti, 1);
659 
660  return ti;
661 }
662 
663 int vnet_tap_connect (vlib_main_t * vm, u8 * intfc_name, u8 *hwaddr_arg,
664  u32 * sw_if_indexp)
665 {
666  tapcli_main_t * tm = &tapcli_main;
667  tapcli_interface_t * ti = NULL;
668  struct ifreq ifr;
669  int flags;
670  int dev_net_tun_fd;
671  int dev_tap_fd = -1;
672  clib_error_t * error;
673  u8 hwaddr [6];
674  int rv = 0;
675 
676  if (tm->is_disabled)
677  {
678  return VNET_API_ERROR_FEATURE_DISABLED;
679  }
680 
681  flags = IFF_TAP | IFF_NO_PI;
682 
683  if ((dev_net_tun_fd = open ("/dev/net/tun", O_RDWR)) < 0)
684  return VNET_API_ERROR_SYSCALL_ERROR_1;
685 
686  memset (&ifr, 0, sizeof (ifr));
687  strncpy(ifr.ifr_name, (char *) intfc_name, sizeof (ifr.ifr_name)-1);
688  ifr.ifr_flags = flags;
689  if (ioctl (dev_net_tun_fd, TUNSETIFF, (void *)&ifr) < 0)
690  {
691  rv = VNET_API_ERROR_SYSCALL_ERROR_2;
692  goto error;
693  }
694 
695  /* Open a provisioning socket */
696  if ((dev_tap_fd = socket(PF_PACKET, SOCK_RAW,
697  htons(ETH_P_ALL))) < 0 )
698  {
699  rv = VNET_API_ERROR_SYSCALL_ERROR_3;
700  goto error;
701  }
702 
703  /* Find the interface index. */
704  {
705  struct ifreq ifr;
706  struct sockaddr_ll sll;
707 
708  memset (&ifr, 0, sizeof(ifr));
709  strncpy (ifr.ifr_name, (char *) intfc_name, sizeof (ifr.ifr_name)-1);
710  if (ioctl (dev_tap_fd, SIOCGIFINDEX, &ifr) < 0 )
711  {
712  rv = VNET_API_ERROR_SYSCALL_ERROR_4;
713  goto error;
714  }
715 
716  /* Bind the provisioning socket to the interface. */
717  memset(&sll, 0, sizeof(sll));
718  sll.sll_family = AF_PACKET;
719  sll.sll_ifindex = ifr.ifr_ifindex;
720  sll.sll_protocol = htons(ETH_P_ALL);
721 
722  if (bind(dev_tap_fd, (struct sockaddr*) &sll, sizeof(sll)) < 0)
723  {
724  rv = VNET_API_ERROR_SYSCALL_ERROR_5;
725  goto error;
726  }
727  }
728 
729  /* non-blocking I/O on /dev/tapX */
730  {
731  int one = 1;
732  if (ioctl (dev_net_tun_fd, FIONBIO, &one) < 0)
733  {
734  rv = VNET_API_ERROR_SYSCALL_ERROR_6;
735  goto error;
736  }
737  }
738  ifr.ifr_mtu = tm->mtu_bytes;
739  if (ioctl (dev_tap_fd, SIOCSIFMTU, &ifr) < 0)
740  {
741  rv = VNET_API_ERROR_SYSCALL_ERROR_7;
742  goto error;
743  }
744 
745  /* get flags, modify to bring up interface... */
746  if (ioctl (dev_tap_fd, SIOCGIFFLAGS, &ifr) < 0)
747  {
748  rv = VNET_API_ERROR_SYSCALL_ERROR_8;
749  goto error;
750  }
751 
752  ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
753 
754  if (ioctl (dev_tap_fd, SIOCSIFFLAGS, &ifr) < 0)
755  {
756  rv = VNET_API_ERROR_SYSCALL_ERROR_9;
757  goto error;
758  }
759 
760  if (ioctl (dev_tap_fd, SIOCGIFHWADDR, &ifr) < 0)
761  {
762  rv = VNET_API_ERROR_SYSCALL_ERROR_1;
763  goto error;
764  }
765 
766  ti = tapcli_get_new_tapif();
767  ti->per_interface_next_index = ~0;
768 
769  if (hwaddr_arg != 0)
770  clib_memcpy(hwaddr, hwaddr_arg, 6);
771 
773  (tm->vnet_main,
774  tapcli_dev_class.index,
775  ti - tm->tapcli_interfaces /* device instance */,
776  hwaddr_arg != 0 ? hwaddr :
777  (u8 *) ifr.ifr_hwaddr.sa_data /* ethernet address */,
778  &ti->hw_if_index,
780 
781  if (error)
782  {
783  clib_error_report (error);
784  rv = VNET_API_ERROR_INVALID_REGISTRATION;
785  goto error;
786  }
787 
788  {
789  unix_file_t template = {0};
790  template.read_function = tapcli_read_ready;
791  template.file_descriptor = dev_net_tun_fd;
792  ti->unix_file_index = unix_file_add (&unix_main, &template);
793  ti->unix_fd = dev_net_tun_fd;
794  ti->provision_fd = dev_tap_fd;
795  clib_memcpy (&ti->ifr, &ifr, sizeof (ifr));
796  }
797 
798  {
799  vnet_hw_interface_t * hw;
804  ti->sw_if_index = hw->sw_if_index;
805  if (sw_if_indexp)
806  *sw_if_indexp = hw->sw_if_index;
807  }
808 
809  ti->active = 1;
810 
812  ti - tm->tapcli_interfaces);
813 
815  ti - tm->tapcli_interfaces);
816 
817  return rv;
818 
819  error:
820  close (dev_net_tun_fd);
821  close (dev_tap_fd);
822 
823  return rv;
824 }
825 
826 int vnet_tap_connect_renumber (vlib_main_t * vm, u8 * intfc_name,
827  u8 *hwaddr_arg, u32 * sw_if_indexp,
828  u8 renumber, u32 custom_dev_instance)
829 {
830  int rv = vnet_tap_connect(vm, intfc_name, hwaddr_arg, sw_if_indexp);
831 
832  if (!rv && renumber)
833  vnet_interface_name_renumber (*sw_if_indexp, custom_dev_instance);
834 
835  return rv;
836 }
837 
839 {
840  int rv = 0;
841  vnet_main_t * vnm = vnet_get_main();
842  tapcli_main_t * tm = &tapcli_main;
843  u32 sw_if_index = ti->sw_if_index;
844 
845  // bring interface down
846  vnet_sw_interface_set_flags (vnm, sw_if_index, 0);
847 
848  if (ti->unix_file_index != ~0) {
850  ti->unix_file_index = ~0;
851  }
852 
855  close(ti->unix_fd);
856  close(ti->provision_fd);
857  ti->unix_fd = -1;
858  ti->provision_fd = -1;
859 
860  return rv;
861 }
862 
863 int vnet_tap_delete(vlib_main_t *vm, u32 sw_if_index)
864 {
865  int rv = 0;
866  tapcli_main_t * tm = &tapcli_main;
867  tapcli_interface_t *ti;
868  uword *p = NULL;
869 
871  sw_if_index);
872  if (p == 0) {
873  clib_warning ("sw_if_index %d unknown", sw_if_index);
874  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
875  }
876  ti = vec_elt_at_index (tm->tapcli_interfaces, p[0]);
877 
878  // inactive
879  ti->active = 0;
881  // add to inactive list
883 
884  // reset renumbered iface
887 
889  return rv;
890 }
891 
892 static clib_error_t *
894  unformat_input_t * input,
895  vlib_cli_command_t * cmd)
896 {
897  tapcli_main_t * tm = &tapcli_main;
898  u32 sw_if_index = ~0;
899 
900  if (tm->is_disabled)
901  {
902  return clib_error_return (0, "device disabled...");
903  }
904 
905  if (unformat (input, "%U", unformat_vnet_sw_interface, tm->vnet_main,
906  &sw_if_index))
907  ;
908  else
909  return clib_error_return (0, "unknown input `%U'",
910  format_unformat_error, input);
911 
912 
913  int rc = vnet_tap_delete (vm, sw_if_index);
914 
915  if (!rc) {
916  vlib_cli_output (vm, "Deleted.");
917  } else {
918  vlib_cli_output (vm, "Error during deletion of tap interface. (rc: %d)", rc);
919  }
920 
921  return 0;
922 }
923 
924 VLIB_CLI_COMMAND (tap_delete_command, static) = {
925  .path = "tap delete",
926  .short_help = "tap delete <vpp-tap-intfc-name>",
927  .function = tap_delete_command_fn,
928 };
929 
930 /* modifies tap interface - can result in new interface being created */
931 int vnet_tap_modify (vlib_main_t * vm, u32 orig_sw_if_index,
932  u8 * intfc_name, u8 *hwaddr_arg,
933  u32 * sw_if_indexp,
934  u8 renumber, u32 custom_dev_instance)
935 {
936  int rv = vnet_tap_delete (vm, orig_sw_if_index);
937 
938  if (rv)
939  return rv;
940 
941  rv = vnet_tap_connect_renumber(vm, intfc_name, hwaddr_arg, sw_if_indexp,
942  renumber, custom_dev_instance);
943 
944  return rv;
945 }
946 
947 static clib_error_t *
949  unformat_input_t * input,
950  vlib_cli_command_t * cmd)
951 {
952  u8 * intfc_name;
953  tapcli_main_t * tm = &tapcli_main;
954  u32 sw_if_index = ~0;
955  u32 new_sw_if_index = ~0;
956  int user_hwaddr = 0;
957  u8 hwaddr[6];
958 
959  if (tm->is_disabled)
960  {
961  return clib_error_return (0, "device disabled...");
962  }
963 
964  if (unformat (input, "%U", unformat_vnet_sw_interface, tm->vnet_main,
965  &sw_if_index))
966  ;
967  else
968  return clib_error_return (0, "unknown input `%U'",
969  format_unformat_error, input);
970 
971  if (unformat (input, "%s", &intfc_name))
972  ;
973  else
974  return clib_error_return (0, "unknown input `%U'",
975  format_unformat_error, input);
976 
977  if (unformat(input, "hwaddr %U", unformat_ethernet_address,
978  &hwaddr))
979  user_hwaddr = 1;
980 
981 
982  int rc = vnet_tap_modify (vm, sw_if_index, intfc_name,
983  (user_hwaddr == 1 ? hwaddr : 0),
984  &new_sw_if_index, 0, 0);
985 
986  if (!rc) {
987  vlib_cli_output (vm, "Modified %U for Linux tap '%s'",
989  new_sw_if_index, intfc_name);
990  } else {
991  vlib_cli_output (vm, "Error during modification of tap interface. (rc: %d)", rc);
992  }
993 
994  return 0;
995 }
996 
997 VLIB_CLI_COMMAND (tap_modify_command, static) = {
998  .path = "tap modify",
999  .short_help = "tap modify <vpp-tap-intfc-name> <linux-intfc-name> [hwaddr [<addr> | random]]",
1000  .function = tap_modify_command_fn,
1001 };
1002 
1003 static clib_error_t *
1005  unformat_input_t * input,
1006  vlib_cli_command_t * cmd)
1007 {
1008  u8 * intfc_name;
1009  tapcli_main_t * tm = &tapcli_main;
1010  int user_hwaddr = 0;
1011  u8 hwaddr[6];
1012  u8 *hwaddr_arg = 0;
1013  u32 sw_if_index;
1014 
1015  if (tm->is_disabled)
1016  {
1017  return clib_error_return (0, "device disabled...");
1018  }
1019 
1020  if (unformat (input, "%s", &intfc_name))
1021  ;
1022  else
1023  return clib_error_return (0, "unknown input `%U'",
1024  format_unformat_error, input);
1025 
1026  if (unformat(input, "hwaddr %U", unformat_ethernet_address,
1027  &hwaddr))
1028  user_hwaddr = 1;
1029 
1030  if (unformat(input, "hwaddr random"))
1031  {
1032  f64 now = vlib_time_now(vm);
1033  u32 rnd;
1034  rnd = (u32) (now * 1e6);
1035  rnd = random_u32 (&rnd);
1036 
1037  clib_memcpy (hwaddr+2, &rnd, sizeof(rnd));
1038  hwaddr[0] = 2;
1039  hwaddr[1] = 0xfe;
1040  user_hwaddr = 1;
1041  }
1042  if (user_hwaddr) hwaddr_arg = hwaddr;
1043 
1044  int rv = vnet_tap_connect(vm, intfc_name, hwaddr_arg, &sw_if_index);
1045  if (rv) {
1046  switch (rv) {
1047  case VNET_API_ERROR_SYSCALL_ERROR_1:
1048  vlib_cli_output (vm, "Couldn't open /dev/net/tun");
1049  break;
1050 
1051  case VNET_API_ERROR_SYSCALL_ERROR_2:
1052  vlib_cli_output (vm, "Error setting flags on '%s'", intfc_name);
1053  break;
1054 
1055  case VNET_API_ERROR_SYSCALL_ERROR_3:
1056  vlib_cli_output (vm, "Couldn't open provisioning socket");
1057  break;
1058 
1059  case VNET_API_ERROR_SYSCALL_ERROR_4:
1060  vlib_cli_output (vm, "Couldn't get if_index");
1061  break;
1062 
1063  case VNET_API_ERROR_SYSCALL_ERROR_5:
1064  vlib_cli_output (vm, "Couldn't bind provisioning socket");
1065  break;
1066 
1067  case VNET_API_ERROR_SYSCALL_ERROR_6:
1068  vlib_cli_output (0, "Couldn't set device non-blocking flag");
1069  break;
1070 
1071  case VNET_API_ERROR_SYSCALL_ERROR_7:
1072  vlib_cli_output (0, "Couldn't set device MTU");
1073  break;
1074 
1075  case VNET_API_ERROR_SYSCALL_ERROR_8:
1076  vlib_cli_output (0, "Couldn't get interface flags");
1077  break;
1078 
1079  case VNET_API_ERROR_SYSCALL_ERROR_9:
1080  vlib_cli_output (0, "Couldn't set intfc admin state up");
1081  break;
1082 
1083  case VNET_API_ERROR_INVALID_REGISTRATION:
1084  vlib_cli_output (0, "Invalid registration");
1085  break;
1086  default:
1087  vlib_cli_output (0, "Unknown error: %d", rv);
1088  break;
1089  }
1090  return 0;
1091  }
1092 
1093  vlib_cli_output (vm, "Created %U for Linux tap '%s'",
1095  sw_if_index, intfc_name);
1096 
1097  return 0;
1098 
1099  }
1100 
1101 VLIB_CLI_COMMAND (tap_connect_command, static) = {
1102  .path = "tap connect",
1103  .short_help = "tap connect <intfc-name> [hwaddr [<addr> | random]]",
1104  .function = tap_connect_command_fn,
1105 };
1106 
1107 clib_error_t *
1109 {
1110  tapcli_main_t * tm = &tapcli_main;
1111 
1112  tm->vlib_main = vm;
1113  tm->vnet_main = vnet_get_main();
1114  tm->unix_main = &unix_main;
1115  tm->mtu_bytes = TAP_MTU_DEFAULT;
1118  tm->rx_buffers = 0;
1122  return 0;
1123 }
1124 
u32 per_interface_next_index
Definition: tapcli.c:59
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:394
unix_file_t * file_pool
Definition: unix.h:85
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Definition: main.c:459
vlib_main_t * vlib_main
Definition: tapcli.c:114
static int tap_name_renumber(vnet_hw_interface_t *hi, u32 new_dev_instance)
Definition: tapcli.c:465
vmrglw vmrglh hi
u32 * show_dev_instance_by_real_dev_instance
Definition: tapcli.c:108
#define hash_set(h, key, value)
Definition: hash.h:237
void(* os_punt_frame)(struct vlib_main_t *vm, struct vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: main.h:128
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword * tapcli_interface_index_by_unix_fd
Definition: tapcli.c:105
int vnet_tap_modify(vlib_main_t *vm, u32 orig_sw_if_index, u8 *intfc_name, u8 *hwaddr_arg, u32 *sw_if_indexp, u8 renumber, u32 custom_dev_instance)
Definition: tapcli.c:931
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
#define VNET_HW_INTERFACE_FLAG_SPEED_1G
Definition: interface.h:254
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:454
vlib_node_registration_t tapcli_tx_node
(constructor) VLIB_REGISTER_NODE (tapcli_tx_node)
Definition: tapcli.c:201
unix_file_function_t * read_function
Definition: unix.h:61
#define hash_unset(h, key)
Definition: hash.h:243
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:205
vnet_interface_main_t interface_main
Definition: vnet.h:62
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:383
static clib_error_t * tap_delete_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: tapcli.c:893
#define PREDICT_TRUE(x)
Definition: clib.h:98
#define UNFORMAT_END_OF_INPUT
Definition: format.h:142
#define NULL
Definition: clib.h:55
always_inline uword unix_file_add(unix_main_t *um, unix_file_t *template)
Definition: unix.h:131
always_inline void vlib_set_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt, u32 count)
Definition: trace_funcs.h:160
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
int vnet_interface_name_renumber(u32 sw_if_index, u32 new_show_dev_instance)
Definition: interface.c:1028
always_inline void vlib_node_set_interrupt_pending(vlib_main_t *vm, u32 node_index)
Definition: node_funcs.h:134
struct _vlib_node_registration vlib_node_registration_t
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:519
unformat_function_t unformat_vnet_sw_interface
#define clib_error_report(e)
Definition: error.h:126
VNET_DEVICE_CLASS(tapcli_dev_class, static)
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:241
static clib_error_t * tapcli_read_ready(unix_file_t *uf)
Definition: tapcli.c:412
struct _vnet_device_class vnet_device_class_t
vlib_error_t * errors
Definition: node.h:378
#define vec_alloc(V, N)
Allocate space for N more elements (no header, unspecified alignment)
Definition: vec.h:237
format_function_t format_vnet_sw_if_index_name
always_inline vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
struct iovec * iovecs
Definition: tapcli.c:80
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
always_inline uword unformat_check_input(unformat_input_t *i)
Definition: format.h:168
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
#define foreach_tapcli_error
Definition: tapcli.h:21
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:77
static clib_error_t * tap_modify_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: tapcli.c:948
always_inline u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
Definition: trace_funcs.h:144
static vnet_device_class_t tapcli_dev_class
Definition: tapcli.c:44
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:109
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:458
always_inline void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
Definition: counter.h:210
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static tapcli_main_t tapcli_main
Definition: tapcli.c:119
#define clib_warning(format, args...)
Definition: error.h:59
static clib_error_t * tapcli_config(vlib_main_t *vm, unformat_input_t *input)
Definition: tapcli.c:434
static tapcli_interface_t * tapcli_get_new_tapif()
Definition: tapcli.c:638
always_inline u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:68
always_inline void * vlib_frame_vector_args(vlib_frame_t *f)
Definition: node_funcs.h:202
u32 unix_file_index
Definition: tapcli.c:53
#define VLIB_BUFFER_NEXT_PRESENT
Definition: buffer.h:93
u32 max_supported_packet_bytes
Definition: interface.h:299
#define hash_get(h, key)
Definition: hash.h:231
#define clib_bitmap_foreach(i, ai, body)
Definition: bitmap.h:308
u32 file_descriptor
Definition: unix.h:51
void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer.c:1060
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:81
static vnet_hw_interface_class_t tapcli_interface_class
Definition: tapcli.c:45
void vlib_frame_free(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_frame_t *f)
Definition: main.c:211
uword * tapcli_interface_index_by_sw_if_index
Definition: tapcli.c:102
uword os_get_cpu_number(void)
Definition: unix-misc.c:206
static uword tapcli_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: tapcli.c:128
static char * tapcli_rx_error_strings[]
Definition: tapcli.c:386
u32 vlib_buffer_alloc_from_free_list(vlib_main_t *vm, u32 *buffers, u32 n_buffers, u32 free_list_index)
Allocate buffers from specific freelist into supplied array.
Definition: buffer.c:782
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:116
vnet_main_t vnet_main
Definition: misc.c:42
always_inline uword * clib_bitmap_set(uword *ai, uword i, uword value)
Definition: bitmap.h:132
always_inline void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:970
#define VLIB_FRAME_SIZE
Definition: node.h:292
struct ifreq ifr
Definition: tapcli.c:58
static u32 tapcli_flag_change(vnet_main_t *vnm, vnet_hw_interface_t *hw, u32 flags)
Definition: tapcli.c:512
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Definition: buffer_node.h:83
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:265
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
u32 mtu_bytes
Definition: tapcli.c:90
always_inline void * vlib_frame_args(vlib_frame_t *f)
Definition: node_funcs.h:209
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:129
#define TAP_MTU_DEFAULT
Definition: tapcli.h:43
u32 mtu_buffers
Definition: tapcli.c:90
u16 n_vectors
Definition: node.h:307
static uword tapcli_rx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: tapcli.c:355
static int tapcli_tap_disconnect(tapcli_interface_t *ti)
Definition: tapcli.c:838
static void tapcli_nopunt_frame(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: tapcli.c:482
#define clib_memcpy(a, b, c)
Definition: string.h:63
always_inline vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
tapcli_interface_t * tapcli_interfaces
Definition: tapcli.c:93
#define clib_unix_warning(format, args...)
Definition: error.h:68
#define VLIB_BUFFER_TOTAL_LENGTH_VALID
Definition: buffer.h:95
#define ETHERNET_INTERFACE_FLAG_MTU
Definition: ethernet.h:86
#define ETHERNET_INTERFACE_FLAG_ACCEPT_ALL
Definition: ethernet.h:81
always_inline vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
u32 * rx_buffers
Definition: tapcli.c:84
static u8 * format_tapcli_interface_name(u8 *s, va_list *args)
Definition: tapcli.c:496
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:150
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
Definition: buffer.h:296
#define hash_create(elts, value_bytes)
Definition: hash.h:615
#define VNET_HW_INTERFACE_FLAG_FULL_DUPLEX
Definition: interface.h:245
u16 cached_next_index
Definition: node.h:422
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:373
always_inline void unix_file_del(unix_main_t *um, unix_file_t *f)
Definition: unix.h:141
u32 max_l3_packet_bytes[VLIB_N_RX_TX]
Definition: interface.h:313
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:187
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:87
#define vnet_buffer(b)
Definition: buffer.h:300
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
#define TAP_MTU_MAX
Definition: tapcli.h:42
static uword tapcli_rx_iface(vlib_main_t *vm, vlib_node_runtime_t *node, tapcli_interface_t *ti)
Definition: tapcli.c:218
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:112
clib_error_t * ethernet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u8 *address, u32 *hw_if_index_return, ethernet_flag_change_function_t flag_change)
Definition: interface.c:157
u8 * format_tapcli_rx_trace(u8 *s, va_list *va)
Definition: tapcli.c:67
u32 clone_count
Specifies whether this buffer should be reinitialized when freed.
Definition: buffer.h:121
int vnet_tap_delete(vlib_main_t *vm, u32 sw_if_index)
Definition: tapcli.c:863
static clib_error_t * tapcli_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: tapcli.c:590
unix_main_t unix_main
Definition: main.c:57
always_inline uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:919
VNET_HW_INTERFACE_CLASS(tapcli_interface_class, static)
u64 uword
Definition: types.h:112
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
Definition: buffer.h:106
Definition: defs.h:46
unsigned short u16
Definition: types.h:57
i64 word
Definition: types.h:111
struct _vnet_hw_interface_class vnet_hw_interface_class_t
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:140
unsigned char u8
Definition: types.h:56
always_inline vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 * tapcli_inactive_interfaces
Definition: tapcli.c:96
int is_disabled
Definition: tapcli.c:111
vnet_main_t * vnet_main
Definition: tapcli.c:115
Definition: unix.h:49
int vnet_tap_connect(vlib_main_t *vm, u8 *intfc_name, u8 *hwaddr_arg, u32 *sw_if_indexp)
Definition: tapcli.c:663
#define VLIB_BUFFER_DATA_SIZE
Definition: buffer.h:55
always_inline void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
static vlib_node_registration_t tapcli_rx_node
(constructor) VLIB_REGISTER_NODE (tapcli_rx_node)
Definition: tapcli.c:46
u32 min_supported_packet_bytes
Definition: interface.h:296
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:140
int vnet_tap_connect_renumber(vlib_main_t *vm, u8 *intfc_name, u8 *hwaddr_arg, u32 *sw_if_indexp, u8 renumber, u32 custom_dev_instance)
Definition: tapcli.c:826
clib_error_t * tapcli_init(vlib_main_t *vm)
Definition: tapcli.c:1108
u8 data[0]
Packet data.
Definition: buffer.h:150
#define vec_foreach(var, vec)
Vector iterator.
always_inline f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: interface.c:462
#define clib_error_return(e, args...)
Definition: error.h:112
void vlib_buffer_chain_validate(vlib_main_t *vm, vlib_buffer_t *b_first)
Definition: buffer.c:1254
struct _unformat_input_t unformat_input_t
#define TAP_MTU_MIN
Definition: tapcli.h:41
u32 flags
Definition: vhost-user.h:73
#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:443
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:84
always_inline void vlib_trace_buffer(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, vlib_buffer_t *b, int follow_chain)
Definition: trace_funcs.h:106
int vnet_tap_dump_ifs(tapcli_interface_details_t **out_tapids)
Definition: tapcli.c:616
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
uword * pending_read_bitmap
Definition: tapcli.c:99
static void tapcli_set_interface_next_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Definition: tapcli.c:564
Definition: defs.h:45
unix_main_t * unix_main
Definition: tapcli.c:116
static clib_error_t * tap_connect_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: tapcli.c:1004