#include <rte_tcp.h>
#include "main.h"
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
#include "vxlan.h"
#include "vxlan_setup.h"
#define RTE_TEST_RX_DESC_DEFAULT 1024
#define RTE_TEST_TX_DESC_DEFAULT 512
+/* Default inner VLAN ID */
+#define INNER_VLAN_ID 100
+
/* VXLAN device */
struct vxlan_conf vxdev;
/* Remote VTEP MAC address */
uint8_t peer_mac[6] = {0x00, 0x11, 0x01, 0x00, 0x00, 0x01};
+/* VXLAN RX filter type */
+uint8_t tep_filter_type[] = {RTE_TUNNEL_FILTER_IMAC_TENID,
+ RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID,
+ RTE_TUNNEL_FILTER_OMAC_TENID_IMAC,};
+
/* Options for configuring ethernet port */
static const struct rte_eth_conf port_conf = {
.rxmode = {
.hw_ip_checksum = 0, /**< IP checksum offload disabled */
.hw_vlan_filter = 0, /**< VLAN filtering disabled */
.jumbo_frame = 0, /**< Jumbo Frame Support disabled */
- .hw_strip_crc = 0, /**< CRC stripped by hardware */
+ .hw_strip_crc = 1, /**< CRC stripped by hardware */
},
.txmode = {
.mq_mode = ETH_MQ_TX_NONE,
uint16_t rx_rings, tx_rings = (uint16_t)rte_lcore_count();
const uint16_t rx_ring_size = RTE_TEST_RX_DESC_DEFAULT;
const uint16_t tx_ring_size = RTE_TEST_TX_DESC_DEFAULT;
+ struct rte_eth_udp_tunnel tunnel_udp;
struct rte_eth_rxconf *rxconf;
struct rte_eth_txconf *txconf;
+ struct vxlan_conf *pconf = &vxdev;
+
+ pconf->dst_port = udp_port;
rte_eth_dev_info_get(port, &dev_info);
if (retval < 0)
return retval;
+ /* Configure UDP port for UDP tunneling */
+ tunnel_udp.udp_port = udp_port;
+ tunnel_udp.prot_type = RTE_TUNNEL_TYPE_VXLAN;
+ retval = rte_eth_dev_udp_tunnel_port_add(port, &tunnel_udp);
+ if (retval < 0)
+ return retval;
rte_eth_macaddr_get(port, &ports_eth_addr[port]);
RTE_LOG(INFO, PORT, "Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
ports_eth_addr[port].addr_bytes[3],
ports_eth_addr[port].addr_bytes[4],
ports_eth_addr[port].addr_bytes[5]);
+
+ if (tso_segsz != 0) {
+ struct rte_eth_dev_info dev_info;
+ rte_eth_dev_info_get(port, &dev_info);
+ if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) == 0)
+ RTE_LOG(WARNING, PORT,
+ "hardware TSO offload is not supported\n");
+ }
return 0;
}
static int
vxlan_rx_process(struct rte_mbuf *pkt)
{
- return decapsulation(pkt);
+ int ret = 0;
+
+ if (rx_decap)
+ ret = decapsulation(pkt);
+
+ return ret;
}
static void
vxlan_tx_process(uint8_t queue_id, struct rte_mbuf *pkt)
{
- encapsulation(pkt, queue_id);
+ if (tx_encap)
+ encapsulation(pkt, queue_id);
+
return;
}
int
vxlan_link(struct vhost_dev *vdev, struct rte_mbuf *m)
{
- int i;
+ int i, ret;
struct ether_hdr *pkt_hdr;
- struct virtio_net *dev = vdev->dev;
- uint64_t portid = dev->device_fh;
+ uint64_t portid = vdev->vid;
struct ipv4_hdr *ip;
- if (unlikely(portid > VXLAN_N_PORTS)) {
+ struct rte_eth_tunnel_filter_conf tunnel_filter_conf;
+
+ if (unlikely(portid >= VXLAN_N_PORTS)) {
RTE_LOG(INFO, VHOST_DATA,
- "(%"PRIu64") WARNING: Not configuring device,"
+ "(%d) WARNING: Not configuring device,"
"as already have %d ports for VXLAN.",
- dev->device_fh, VXLAN_N_PORTS);
+ vdev->vid, VXLAN_N_PORTS);
return -1;
}
pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
if (is_same_ether_addr(&(pkt_hdr->s_addr), &vdev->mac_address)) {
RTE_LOG(INFO, VHOST_DATA,
- "(%"PRIu64") WARNING: This device is using an existing"
+ "(%d) WARNING: This device is using an existing"
" MAC address and has not been registered.\n",
- dev->device_fh);
+ vdev->vid);
return -1;
}
vxdev.port[portid].peer_mac.addr_bytes[i] = peer_mac[i];
}
+ memset(&tunnel_filter_conf, 0,
+ sizeof(struct rte_eth_tunnel_filter_conf));
+
+ ether_addr_copy(&ports_eth_addr[0], &tunnel_filter_conf.outer_mac);
+ tunnel_filter_conf.filter_type = tep_filter_type[filter_idx];
+
+ /* inner MAC */
+ ether_addr_copy(&vdev->mac_address, &tunnel_filter_conf.inner_mac);
+
+ tunnel_filter_conf.queue_id = vdev->rx_q;
+ tunnel_filter_conf.tenant_id = tenant_id_conf[vdev->rx_q];
+
+ if (tep_filter_type[filter_idx] == RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID)
+ tunnel_filter_conf.inner_vlan = INNER_VLAN_ID;
+
+ tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_VXLAN;
+
+ ret = rte_eth_dev_filter_ctrl(ports[0],
+ RTE_ETH_FILTER_TUNNEL,
+ RTE_ETH_FILTER_ADD,
+ &tunnel_filter_conf);
+ if (ret) {
+ RTE_LOG(ERR, VHOST_DATA,
+ "%d Failed to add device MAC address to cloud filter\n",
+ vdev->rx_q);
+ return -1;
+ }
+
/* Print out inner MAC and VNI info. */
RTE_LOG(INFO, VHOST_DATA,
"(%d) MAC_ADDRESS %02x:%02x:%02x:%02x:%02x:%02x and VNI %d registered\n",
vxlan_unlink(struct vhost_dev *vdev)
{
unsigned i = 0, rx_count;
+ int ret;
struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_eth_tunnel_filter_conf tunnel_filter_conf;
if (vdev->ready == DEVICE_RX) {
+ memset(&tunnel_filter_conf, 0,
+ sizeof(struct rte_eth_tunnel_filter_conf));
+
+ ether_addr_copy(&ports_eth_addr[0], &tunnel_filter_conf.outer_mac);
+ ether_addr_copy(&vdev->mac_address, &tunnel_filter_conf.inner_mac);
+ tunnel_filter_conf.tenant_id = tenant_id_conf[vdev->rx_q];
+ tunnel_filter_conf.filter_type = tep_filter_type[filter_idx];
+
+ if (tep_filter_type[filter_idx] ==
+ RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID)
+ tunnel_filter_conf.inner_vlan = INNER_VLAN_ID;
+
+ tunnel_filter_conf.queue_id = vdev->rx_q;
+ tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_VXLAN;
+
+ ret = rte_eth_dev_filter_ctrl(ports[0],
+ RTE_ETH_FILTER_TUNNEL,
+ RTE_ETH_FILTER_DELETE,
+ &tunnel_filter_conf);
+ if (ret) {
+ RTE_LOG(ERR, VHOST_DATA,
+ "%d Failed to add device MAC address to cloud filter\n",
+ vdev->rx_q);
+ return;
+ }
for (i = 0; i < ETHER_ADDR_LEN; i++)
vdev->mac_address.addr_bytes[i] = 0;
/* Check for decapsulation and pass packets directly to VIRTIO device */
int
-vxlan_rx_pkts(struct virtio_net *dev, struct rte_mbuf **pkts_burst,
- uint32_t rx_count)
+vxlan_rx_pkts(int vid, struct rte_mbuf **pkts_burst, uint32_t rx_count)
{
uint32_t i = 0;
uint32_t count = 0;
struct rte_mbuf *pkts_valid[rx_count];
for (i = 0; i < rx_count; i++) {
+ if (enable_stats) {
+ rte_atomic64_add(
+ &dev_statistics[vid].rx_bad_ip_csum,
+ (pkts_burst[i]->ol_flags & PKT_RX_IP_CKSUM_BAD)
+ != 0);
+ rte_atomic64_add(
+ &dev_statistics[vid].rx_bad_ip_csum,
+ (pkts_burst[i]->ol_flags & PKT_RX_L4_CKSUM_BAD)
+ != 0);
+ }
ret = vxlan_rx_process(pkts_burst[i]);
if (unlikely(ret < 0))
continue;
count++;
}
- ret = rte_vhost_enqueue_burst(dev, VIRTIO_RXQ, pkts_valid, count);
+ ret = rte_vhost_enqueue_burst(vid, VIRTIO_RXQ, pkts_valid, count);
return ret;
}