#include <vnet/ip/ip.h>
#include <vnet/ethernet/ethernet.h>
+#include <vnet/devices/devices.h>
+#include <vnet/feature/feature.h>
#if DPDK == 1
#include <vnet/devices/dpdk/dpdk.h>
u32 * buffers = vlib_frame_args (frame);
uword n_packets = frame->n_vectors;
tuntap_main_t * tm = &tuntap_main;
+ vnet_main_t *vnm = vnet_get_main ();
+ vnet_interface_main_t *im = &vnm->interface_main;
+ u32 n_bytes = 0;
int i;
for (i = 0; i < n_packets; i++)
if (writev (tm->dev_net_tun_fd, tm->iovecs, vec_len (tm->iovecs)) < l)
clib_unix_warning ("writev");
+
+ n_bytes += l;
}
+ /* Update tuntap interface output stats. */
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_TX,
+ vm->cpu_index,
+ tm->sw_if_index, n_packets, n_bytes);
+
+
/** The normal interface path flattens the buffer chain */
if (tm->have_normal_interface)
vlib_buffer_free_no_next (vm, buffers, n_packets);
.vector_size = 4,
};
-enum {
- TUNTAP_RX_NEXT_IP4_INPUT,
- TUNTAP_RX_NEXT_IP6_INPUT,
- TUNTAP_RX_NEXT_ETHERNET_INPUT,
- TUNTAP_RX_NEXT_DROP,
- TUNTAP_RX_N_NEXT,
-};
-
/**
* @brief TUNTAP receive node
* @node tuntap-rx
if (tm->is_ether)
{
- next_index = TUNTAP_RX_NEXT_ETHERNET_INPUT;
+ next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT;
}
else
switch (b->data[0] & 0xf0)
{
case 0x40:
- next_index = TUNTAP_RX_NEXT_IP4_INPUT;
+ next_index = VNET_DEVICE_INPUT_NEXT_IP4_INPUT;
break;
case 0x60:
- next_index = TUNTAP_RX_NEXT_IP6_INPUT;
+ next_index = VNET_DEVICE_INPUT_NEXT_IP6_INPUT;
break;
default:
- next_index = TUNTAP_RX_NEXT_DROP;
+ next_index = VNET_DEVICE_INPUT_NEXT_DROP;
break;
}
vnet_sw_interface_t * si;
si = vnet_get_sw_interface (vnm, tm->sw_if_index);
if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
- next_index = TUNTAP_RX_NEXT_DROP;
+ next_index = VNET_DEVICE_INPUT_NEXT_DROP;
}
+ vnet_feature_start_device_input_x1 (tm->sw_if_index, &next_index, b, 0);
+
vlib_set_next_frame_buffer (vm, node, next_index, bi);
if (n_trace > 0)
.n_errors = 1,
.error_strings = tuntap_rx_error_strings,
- .n_next_nodes = TUNTAP_RX_N_NEXT,
- .next_nodes = {
- [TUNTAP_RX_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
- [TUNTAP_RX_NEXT_IP6_INPUT] = "ip6-input",
- [TUNTAP_RX_NEXT_DROP] = "error-drop",
- [TUNTAP_RX_NEXT_ETHERNET_INPUT] = "ethernet-input",
- },
+ .n_next_nodes = VNET_DEVICE_INPUT_N_NEXT_NODES,
+ .next_nodes = VNET_DEVICE_INPUT_NEXT_NODES,
};
/**
snprintf (ifr.ifr_name, sizeof(ifr.ifr_name),
"%s:%d", tm->tun_name, (int)(ap - tm->subifs));
+ /* the tuntap punt/inject is enabled for IPv4 RX so long as
+ * any vpp interface has an IPv4 address.
+ * this is also ref counted.
+ */
+ ip4_sw_interface_enable_disable (tm->sw_if_index, !is_delete);
+
if (! is_delete)
{
struct sockaddr_in * sin;
}
/**
- * @brief workaround for a known #include bug
- * #include <linux/ipv6.h> causes multiple definitions if
- * netinet/in.h is also included.
+ * @brief workaround for a known include file bug.
+ * including @c <linux/ipv6.h> causes multiple definitions if
+ * @c <netinet/in.h is also included.
*/
struct in6_ifreq {
struct in6_addr ifr6_addr;
};
/**
- * @brief Add or Del tun/tap interface address
+ * @brief Add or Del tun/tap interface address.
*
* Both the v6 interface address API and the way ifconfig
* displays subinterfaces differ from their v4 couterparts.
snprintf (ifr.ifr_name, sizeof(ifr.ifr_name),
"%s:%d", tm->tun_name, (int)(ap - tm->subifs));
+ /* the tuntap punt/inject is enabled for IPv6 RX so long as
+ * any vpp interface has an IPv6 address.
+ * this is also ref counted.
+ */
+ ip6_sw_interface_enable_disable (tm->sw_if_index, !is_delete);
+
if (! is_delete)
{
int sockfd = socket (AF_INET6, SOCK_STREAM, 0);
VNET_HW_INTERFACE_CLASS (tuntap_interface_class,static) = {
.name = "tuntap",
+ .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
};
/**