21 #include <sys/ioctl.h> 22 #include <sys/socket.h> 24 #include <sys/types.h> 26 #include <netinet/in.h> 28 #include <linux/if_arp.h> 29 #include <linux/if_tun.h> 138 for (i = 0; i < n_packets; i++)
150 if (tx_sw_if_index == (
u32)~0)
163 clib_warning (
"sw_if_index %d unknown", tx_sw_if_index);
172 _vec_len (tm->
iovecs) = 0;
231 u32 n_left_to_next, next_index;
240 while (n_left_to_next) {
243 word n_bytes_in_packet;
266 tm->
iovecs[j].iov_len = buffer_size;
270 n_bytes_in_packet = n_bytes_left;
271 if (n_bytes_left <= 0) {
272 if (errno != EAGAIN) {
274 TAPCLI_ERROR_READ, 1);
284 b->
current_length = n_bytes_left < buffer_size ? n_bytes_left : buffer_size;
285 n_bytes_left -= buffer_size;
294 if (n_bytes_left <= 0)
305 (n_bytes_in_packet > buffer_size) ? n_bytes_in_packet - buffer_size : 0;
322 to_next[0] = bi_first;
327 to_next, n_left_to_next,
328 bi_first, next_index);
336 1, n_bytes_in_packet);
360 static u32 * ready_interface_indices;
368 vec_add1 (ready_interface_indices, i);
371 if (
vec_len (ready_interface_indices) == 0)
374 for (i = 0; i <
vec_len(ready_interface_indices); i++)
378 ready_interface_indices[i], 0);
387 #define _(sym,string) string, 396 .state = VLIB_NODE_STATE_INTERRUPT,
443 else if (
unformat (input,
"disable"))
466 u32 new_dev_instance)
499 u32 show_dev_instance = ~0;
505 if (show_dev_instance != ~0)
506 i = show_dev_instance;
508 s =
format (s,
"tap-%d", i);
532 memcpy (&ifr, &ti->
ifr, sizeof (ifr));
547 ifr.ifr_flags |= IFF_PROMISC;
549 ifr.ifr_flags &= ~(IFF_PROMISC);
575 if (node_index == ~0)
600 hw_flags = speed_duplex;
613 .no_flatten_output_chains = 1,
629 strncpy((
char *)tapid->
dev_name, ti->
ifr.ifr_name, sizeof (ti->
ifr.ifr_name)-1);
632 *out_tapids = r_tapids;
645 if (inactive_cnt > 0) {
678 return VNET_API_ERROR_FEATURE_DISABLED;
681 flags = IFF_TAP | IFF_NO_PI;
683 if ((dev_net_tun_fd = open (
"/dev/net/tun", O_RDWR)) < 0)
684 return VNET_API_ERROR_SYSCALL_ERROR_1;
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)
691 rv = VNET_API_ERROR_SYSCALL_ERROR_2;
696 if ((dev_tap_fd = socket(PF_PACKET, SOCK_RAW,
697 htons(ETH_P_ALL))) < 0 )
699 rv = VNET_API_ERROR_SYSCALL_ERROR_3;
706 struct sockaddr_ll sll;
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 )
712 rv = VNET_API_ERROR_SYSCALL_ERROR_4;
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);
722 if (bind(dev_tap_fd, (
struct sockaddr*) &sll,
sizeof(sll)) < 0)
724 rv = VNET_API_ERROR_SYSCALL_ERROR_5;
732 if (ioctl (dev_net_tun_fd, FIONBIO, &one) < 0)
734 rv = VNET_API_ERROR_SYSCALL_ERROR_6;
739 if (ioctl (dev_tap_fd, SIOCSIFMTU, &ifr) < 0)
741 rv = VNET_API_ERROR_SYSCALL_ERROR_7;
746 if (ioctl (dev_tap_fd, SIOCGIFFLAGS, &ifr) < 0)
748 rv = VNET_API_ERROR_SYSCALL_ERROR_8;
752 ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
754 if (ioctl (dev_tap_fd, SIOCSIFFLAGS, &ifr) < 0)
756 rv = VNET_API_ERROR_SYSCALL_ERROR_9;
760 if (ioctl (dev_tap_fd, SIOCGIFHWADDR, &ifr) < 0)
762 rv = VNET_API_ERROR_SYSCALL_ERROR_1;
776 hwaddr_arg != 0 ? hwaddr :
777 (
u8 *) ifr.ifr_hwaddr.sa_data ,
784 rv = VNET_API_ERROR_INVALID_REGISTRATION;
791 template.file_descriptor = dev_net_tun_fd;
820 close (dev_net_tun_fd);
827 u8 *hwaddr_arg,
u32 * sw_if_indexp,
828 u8 renumber,
u32 custom_dev_instance)
874 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
898 u32 sw_if_index = ~0;
918 vlib_cli_output (vm,
"Error during deletion of tap interface. (rc: %d)", rc);
925 .path =
"tap delete",
926 .short_help =
"tap delete <vpp-tap-intfc-name>",
932 u8 * intfc_name,
u8 *hwaddr_arg,
934 u8 renumber,
u32 custom_dev_instance)
942 renumber, custom_dev_instance);
954 u32 sw_if_index = ~0;
955 u32 new_sw_if_index = ~0;
971 if (
unformat (input,
"%s", &intfc_name))
983 (user_hwaddr == 1 ? hwaddr : 0),
984 &new_sw_if_index, 0, 0);
989 new_sw_if_index, intfc_name);
991 vlib_cli_output (vm,
"Error during modification of tap interface. (rc: %d)", rc);
998 .path =
"tap modify",
999 .short_help =
"tap modify <vpp-tap-intfc-name> <linux-intfc-name> [hwaddr [<addr> | random]]",
1010 int user_hwaddr = 0;
1020 if (
unformat (input,
"%s", &intfc_name))
1030 if (
unformat(input,
"hwaddr random"))
1034 rnd = (
u32) (now * 1e6);
1042 if (user_hwaddr) hwaddr_arg = hwaddr;
1047 case VNET_API_ERROR_SYSCALL_ERROR_1:
1051 case VNET_API_ERROR_SYSCALL_ERROR_2:
1055 case VNET_API_ERROR_SYSCALL_ERROR_3:
1059 case VNET_API_ERROR_SYSCALL_ERROR_4:
1063 case VNET_API_ERROR_SYSCALL_ERROR_5:
1067 case VNET_API_ERROR_SYSCALL_ERROR_6:
1071 case VNET_API_ERROR_SYSCALL_ERROR_7:
1075 case VNET_API_ERROR_SYSCALL_ERROR_8:
1079 case VNET_API_ERROR_SYSCALL_ERROR_9:
1083 case VNET_API_ERROR_INVALID_REGISTRATION:
1095 sw_if_index, intfc_name);
1102 .path =
"tap connect",
1103 .short_help =
"tap connect <intfc-name> [hwaddr [<addr> | random]]",
u32 per_interface_next_index
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
static int tap_name_renumber(vnet_hw_interface_t *hi, u32 new_dev_instance)
u32 * show_dev_instance_by_real_dev_instance
#define hash_set(h, key, value)
void(* os_punt_frame)(struct vlib_main_t *vm, struct vlib_node_runtime_t *node, vlib_frame_t *frame)
sll srl srl sll sra u16x4 i
uword * tapcli_interface_index_by_unix_fd
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)
#define VNET_HW_INTERFACE_FLAG_SPEED_1G
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
vlib_node_registration_t tapcli_tx_node
(constructor) VLIB_REGISTER_NODE (tapcli_tx_node)
unix_file_function_t * read_function
#define hash_unset(h, key)
void ethernet_delete_interface(vnet_main_t *vnm, u32 hw_if_index)
vnet_interface_main_t interface_main
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
static clib_error_t * tap_delete_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
always_inline uword unix_file_add(unix_main_t *um, unix_file_t *template)
always_inline void vlib_set_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt, u32 count)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
int vnet_interface_name_renumber(u32 sw_if_index, u32 new_show_dev_instance)
always_inline void vlib_node_set_interrupt_pending(vlib_main_t *vm, u32 node_index)
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.
unformat_function_t unformat_vnet_sw_interface
#define clib_error_report(e)
VNET_DEVICE_CLASS(tapcli_dev_class, static)
#define VNET_HW_INTERFACE_FLAG_LINK_UP
static clib_error_t * tapcli_read_ready(unix_file_t *uf)
struct _vnet_device_class vnet_device_class_t
#define vec_alloc(V, N)
Allocate space for N more elements (no header, unspecified alignment)
format_function_t format_vnet_sw_if_index_name
always_inline vlib_main_t * vlib_get_main(void)
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
vnet_main_t * vnet_get_main(void)
#define foreach_tapcli_error
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
static clib_error_t * tap_modify_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
always_inline u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
static vnet_device_class_t tapcli_dev_class
#define VLIB_INIT_FUNCTION(x)
vlib_combined_counter_main_t * combined_sw_if_counters
always_inline void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
#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
#define clib_warning(format, args...)
static clib_error_t * tapcli_config(vlib_main_t *vm, unformat_input_t *input)
static tapcli_interface_t * tapcli_get_new_tapif()
always_inline u32 random_u32(u32 *seed)
32-bit random number generator
always_inline void * vlib_frame_vector_args(vlib_frame_t *f)
#define VLIB_BUFFER_NEXT_PRESENT
u32 max_supported_packet_bytes
#define clib_bitmap_foreach(i, ai, body)
void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
u16 current_length
Nbytes between current data and the end of this buffer.
static vnet_hw_interface_class_t tapcli_interface_class
void vlib_frame_free(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_frame_t *f)
uword * tapcli_interface_index_by_sw_if_index
uword os_get_cpu_number(void)
static uword tapcli_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static char * tapcli_rx_error_strings[]
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.
#define VLIB_CONFIG_FUNCTION(x, n,...)
always_inline uword * clib_bitmap_set(uword *ai, uword i, uword value)
always_inline void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
static u32 tapcli_flag_change(vnet_main_t *vnm, vnet_hw_interface_t *hw, u32 flags)
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
always_inline void * vlib_frame_args(vlib_frame_t *f)
vlib_error_t error
Error code for buffers to be enqueued to error handler.
static uword tapcli_rx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static int tapcli_tap_disconnect(tapcli_interface_t *ti)
static void tapcli_nopunt_frame(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define clib_memcpy(a, b, c)
always_inline vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
tapcli_interface_t * tapcli_interfaces
#define clib_unix_warning(format, args...)
#define VLIB_BUFFER_TOTAL_LENGTH_VALID
#define ETHERNET_INTERFACE_FLAG_MTU
#define ETHERNET_INTERFACE_FLAG_ACCEPT_ALL
always_inline vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
static u8 * format_tapcli_interface_name(u8 *s, va_list *args)
#define VLIB_CLI_COMMAND(x,...)
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
#define hash_create(elts, value_bytes)
#define VNET_HW_INTERFACE_FLAG_FULL_DUPLEX
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
always_inline void unix_file_del(unix_main_t *um, unix_file_t *f)
u32 max_l3_packet_bytes[VLIB_N_RX_TX]
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
static uword tapcli_rx_iface(vlib_main_t *vm, vlib_node_runtime_t *node, tapcli_interface_t *ti)
u32 next_buffer
Next buffer for this linked-list of buffers.
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)
u8 * format_tapcli_rx_trace(u8 *s, va_list *va)
u32 clone_count
Specifies whether this buffer should be reinitialized when freed.
int vnet_tap_delete(vlib_main_t *vm, u32 sw_if_index)
static clib_error_t * tapcli_interface_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
always_inline uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
VNET_HW_INTERFACE_CLASS(tapcli_interface_class, static)
u32 total_length_not_including_first_buffer
Only valid for first buffer in chain.
struct _vnet_hw_interface_class vnet_hw_interface_class_t
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
always_inline vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 * tapcli_inactive_interfaces
int vnet_tap_connect(vlib_main_t *vm, u8 *intfc_name, u8 *hwaddr_arg, u32 *sw_if_indexp)
#define VLIB_BUFFER_DATA_SIZE
always_inline void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
static vlib_node_registration_t tapcli_rx_node
(constructor) VLIB_REGISTER_NODE (tapcli_rx_node)
u32 min_supported_packet_bytes
#define VLIB_REGISTER_NODE(x,...)
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)
clib_error_t * tapcli_init(vlib_main_t *vm)
#define vec_foreach(var, vec)
Vector iterator.
always_inline f64 vlib_time_now(vlib_main_t *vm)
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
#define clib_error_return(e, args...)
void vlib_buffer_chain_validate(vlib_main_t *vm, vlib_buffer_t *b_first)
#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)
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
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)
int vnet_tap_dump_ifs(tapcli_interface_details_t **out_tapids)
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
uword * pending_read_bitmap
static void tapcli_set_interface_next_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
static clib_error_t * tap_connect_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)