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> 112 .mtu_bytes = 4096 + 256,
131 for (i = 0; i < n_packets; i++)
147 _vec_len (tm->
iovecs) = 0;
233 word i, n_bytes_left, n_bytes_in_packet;
243 tm->
iovecs[
i].iov_len = buffer_size;
247 n_bytes_in_packet = n_bytes_left;
248 if (n_bytes_left <= 0)
260 struct rte_mbuf * mb;
264 mb = rte_mbuf_from_vlib_buffer(b);
268 b->
current_length = n_bytes_left < buffer_size ? n_bytes_left : buffer_size;
270 n_bytes_left -= buffer_size;
275 if (n_bytes_left <= 0)
278 rte_pktmbuf_pkt_len (mb) = n_bytes_in_packet;
299 1, n_bytes_in_packet);
328 switch (b->
data[0] & 0xf0)
365 "unknown packet type",
372 .state = VLIB_NODE_STATE_INTERRUPT,
410 sfd = socket (AF_INET, SOCK_STREAM, 0);
414 memset(&ifr, 0,
sizeof (ifr));
415 strncpy (ifr.ifr_name, tm->
tun_name, sizeof (ifr.ifr_name)-1);
418 if (ioctl (sfd, SIOCGIFFLAGS, &ifr) < 0)
421 ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
423 if (ioctl (sfd, SIOCSIFFLAGS, &ifr) < 0)
445 int flags = IFF_TUN | IFF_NO_PI;
446 int is_enabled = 0, is_ether = 0, have_normal_interface = 0;
453 else if (
unformat (input,
"enable"))
455 else if (
unformat (input,
"disable"))
457 else if (
unformat (input,
"ethernet") ||
460 else if (
unformat (input,
"have-normal-interface") ||
462 have_normal_interface = 1;
463 else if (
unformat (input,
"name %s", &name))
486 flags = IFF_TAP | IFF_NO_PI;
494 memset (&ifr, 0,
sizeof (ifr));
495 strncpy(ifr.ifr_name, tm->
tun_name,
sizeof(ifr.ifr_name)-1);
496 ifr.ifr_flags =
flags;
511 if ((tm->
dev_tap_fd = socket(PF_PACKET, SOCK_RAW,
512 htons(ETH_P_ALL))) < 0 )
521 struct sockaddr_ll sll;
523 memset (&ifr, 0,
sizeof(ifr));
524 strncpy (ifr.ifr_name, tm->
tun_name,
sizeof(ifr.ifr_name)-1);
525 if (ioctl (tm->
dev_tap_fd, SIOCGIFINDEX, &ifr) < 0 )
532 memset(&sll, 0,
sizeof(sll));
533 sll.sll_family = AF_PACKET;
534 sll.sll_ifindex = ifr.ifr_ifindex;
535 sll.sll_protocol = htons(ETH_P_ALL);
537 if (bind(tm->
dev_tap_fd, (
struct sockaddr*) &sll,
sizeof(sll)) < 0)
557 if (ioctl (tm->
dev_tap_fd, SIOCSIFMTU, &ifr) < 0)
564 if (ioctl (tm->
dev_tap_fd, SIOCGIFFLAGS, &ifr) < 0)
570 ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
572 if (ioctl (tm->
dev_tap_fd, SIOCSIFFLAGS, &ifr) < 0)
580 if (ioctl (tm->
dev_tap_fd, SIOCGIFHWADDR, &ifr) < 0)
589 if (have_normal_interface)
652 u32 if_address_index,
665 memset (&subif_addr, 0,
sizeof (subif_addr));
681 memset (&ifr, 0,
sizeof (ifr));
682 snprintf (ifr.ifr_name,
sizeof(ifr.ifr_name),
687 struct sockaddr_in * sin;
689 sin = (
struct sockaddr_in *)&ifr.ifr_addr;
692 sin->sin_family = AF_INET;
694 if (ioctl (tm->
dev_tap_fd, SIOCSIFADDR, &ifr) < 0)
697 sin->sin_addr.s_addr = im->
fib_masks[address_length];
698 if (ioctl (tm->
dev_tap_fd, SIOCSIFNETMASK, &ifr) < 0)
708 if (ioctl (tm->
dev_tap_fd, SIOCGIFFLAGS, &ifr) < 0)
712 ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
714 ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
716 if (ioctl (tm->
dev_tap_fd, SIOCSIFFLAGS, &ifr) < 0)
726 struct in6_addr ifr6_addr;
742 u32 if_address_index,
756 memset (&subif_addr, 0,
sizeof (subif_addr));
758 subif_addr.
is_v6 = 1;
773 memset (&ifr, 0,
sizeof (ifr));
774 memset (&ifr6, 0,
sizeof (ifr6));
775 snprintf (ifr.ifr_name,
sizeof(ifr.ifr_name),
780 int sockfd = socket (AF_INET6, SOCK_STREAM, 0);
784 if (ioctl (sockfd, SIOGIFINDEX, &ifr) < 0)
791 if (ioctl (sockfd, SIOCSIFADDR, &ifr6) < 0)
798 int sockfd = socket (AF_INET6, SOCK_STREAM, 0);
802 if (ioctl (sockfd, SIOGIFINDEX, &ifr) < 0)
809 if (ioctl (sockfd, SIOCDIFADDR, &ifr6) < 0)
847 s =
format (s,
"tuntap-%d", i);
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
static clib_error_t * tuntap_exit(vlib_main_t *vm)
static uword tuntap_rx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
vlib_node_registration_t tuntap_tx_node
(constructor) VLIB_REGISTER_NODE (tuntap_tx_node)
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
#define VLIB_BUFFER_TRACE_TRAJECTORY
Compile time buffer trajectory tracing option Turn this on if you run into "bad monkey" contexts...
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
unix_file_function_t * read_function
void tuntap_ip4_add_del_interface_address(ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_delete)
vnet_interface_main_t interface_main
uword mhash_unset(mhash_t *h, void *key, uword *old_value)
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).
always_inline void vlib_node_set_interrupt_pending(vlib_main_t *vm, u32 node_index)
always_inline uword mhash_set(mhash_t *h, void *key, uword new_value, uword *old_value)
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
#define clib_error_report(e)
#define VNET_HW_INTERFACE_FLAG_LINK_UP
struct _vnet_device_class vnet_device_class_t
struct in6_addr ifr6_addr
#define vec_alloc(V, N)
Allocate space for N more elements (no header, unspecified alignment)
always_inline void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
always_inline vlib_main_t * vlib_get_main(void)
vnet_main_t * vnet_get_main(void)
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
always_inline u32 vlib_get_trace_count(vlib_main_t *vm, vlib_node_runtime_t *rt)
#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)
void vlib_buffer_free_no_next(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers, does not free the buffer chain for each buffer.
u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]
Space for inserting data before buffer start.
static vnet_device_class_t tuntap_dev_class
#define clib_warning(format, args...)
static clib_error_t * tuntap_read_ready(unix_file_t *uf)
#define vlib_call_init_function(vm, x)
u32 vnet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u32 hw_class_index, u32 hw_instance)
static u8 * format_tuntap_interface_name(u8 *s, va_list *args)
#define VLIB_BUFFER_NEXT_PRESENT
#define pool_elt_at_index(p, i)
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.
void vlib_frame_free(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_frame_t *f)
uword os_get_cpu_number(void)
#define clib_error_return_unix(e, args...)
static tuntap_main_t tuntap_main
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 void vlib_buffer_reset(vlib_buffer_t *b)
Reset current header & length to state they were in when packet was received.
always_inline void * vlib_frame_args(vlib_frame_t *f)
static uword tuntap_intfc_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
ip6_add_del_interface_address_callback_t * add_del_interface_address_callbacks
vlib_error_t error
Error code for buffers to be enqueued to error handler.
void tuntap_ip6_add_del_interface_address(ip6_main_t *im, uword opaque, u32 sw_if_index, ip6_address_t *address, u32 address_length, u32 if_address_index, u32 is_delete)
static void tuntap_nopunt_frame(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
ip4_add_del_interface_address_function_t * function
#define VLIB_MAIN_LOOP_EXIT_FUNCTION(x)
#define clib_memcpy(a, b, c)
#define clib_unix_warning(format, args...)
static void tuntap_punt_frame(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
always_inline vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX
ip6_add_del_interface_address_function_t * function
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
vlib_node_registration_t tuntap_rx_node
(constructor) VLIB_REGISTER_NODE (tuntap_rx_node)
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)
int have_normal_interface
VNET_DEVICE_CLASS(tuntap_dev_class, static)
static uword tuntap_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static clib_error_t * tuntap_config(vlib_main_t *vm, unformat_input_t *input)
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)
always_inline void vlib_set_next_frame_buffer(vlib_main_t *vm, vlib_node_runtime_t *node, u32 next_index, u32 buffer_index)
#define VLIB_BUFFER_DATA_SIZE
u32 vlib_buffer_free_list_index
#define VLIB_REGISTER_NODE(x,...)
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
static clib_error_t * tuntap_init(vlib_main_t *vm)
#define clib_error_return(e, args...)
VNET_HW_INTERFACE_CLASS(tuntap_interface_class, static)
static vnet_hw_interface_class_t tuntap_interface_class
static char * tuntap_rx_error_strings[]
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)
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
always_inline uword * mhash_get(mhash_t *h, void *key)