#include <getopt.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/virtio_net.h>
#include <linux/virtio_ring.h>
#include <sys/param.h>
#include <unistd.h>
#include "main.h"
#include "vxlan.h"
#include "vxlan_setup.h"
#define IPV4_HEADER_LEN 20
#define UDP_HEADER_LEN 8
#define VXLAN_HEADER_LEN 8
#define IP_DEFTTL 64
#define IP_DN_FRAGMENT_FLAG 0x0040
#define MAC_ADDR_CMP 0xFFFFFFFFFFFFULL
#define RTE_TEST_RX_DESC_DEFAULT 1024
#define RTE_TEST_TX_DESC_DEFAULT 512
#define INNER_VLAN_ID 100
struct vxlan_conf vxdev;
uint8_t vxlan_multicast_ips[2][4] = { {239, 1, 1, 1 }, {239, 1, 2, 1 } };
uint8_t vxlan_overlay_ips[2][4] = { {192, 168, 10, 1}, {192, 168, 30, 1} };
uint8_t peer_mac[6] = {0x00, 0x11, 0x01, 0x00, 0x00, 0x01};
uint8_t tep_filter_type[] = {RTE_TUNNEL_FILTER_IMAC_TENID,
RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID,
RTE_TUNNEL_FILTER_OMAC_TENID_IMAC,};
},
.txmode = {
.offloads = (DEV_TX_OFFLOAD_IPV4_CKSUM |
DEV_TX_OFFLOAD_UDP_CKSUM |
DEV_TX_OFFLOAD_TCP_CKSUM |
DEV_TX_OFFLOAD_SCTP_CKSUM |
DEV_TX_OFFLOAD_TCP_TSO |
},
};
const uint16_t tenant_id_conf[] = {
1000, 1000, 1001, 1001, 1002, 1002, 1003, 1003,
1004, 1004, 1005, 1005, 1006, 1006, 1007, 1007,
1008, 1008, 1009, 1009, 1010, 1010, 1011, 1011,
1012, 1012, 1013, 1013, 1014, 1014, 1015, 1015,
1016, 1016, 1017, 1017, 1018, 1018, 1019, 1019,
1020, 1020, 1021, 1021, 1022, 1022, 1023, 1023,
1024, 1024, 1025, 1025, 1026, 1026, 1027, 1027,
1028, 1028, 1029, 1029, 1030, 1030, 1031, 1031,
};
int
vxlan_port_init(uint16_t port,
struct rte_mempool *mbuf_pool)
{
int retval;
uint16_t q;
uint16_t rx_ring_size = RTE_TEST_RX_DESC_DEFAULT;
uint16_t tx_ring_size = RTE_TEST_TX_DESC_DEFAULT;
struct vxlan_conf *pconf = &vxdev;
pconf->dst_port = udp_port;
if (retval != 0)
"Error during getting device (port %u) info: %s\n",
port, strerror(-retval));
if (dev_info.max_rx_queues > MAX_QUEUES) {
"please define MAX_QUEUES no less than %u in %s\n",
dev_info.max_rx_queues, __FILE__);
}
rxconf = &dev_info.default_rxconf;
txconf = &dev_info.default_txconf;
return -1;
rx_rings = nb_devices;
&local_port_conf);
if (retval != 0)
return retval;
&tx_ring_size);
if (retval != 0)
return retval;
for (q = 0; q < rx_rings; q++) {
rxconf,
mbuf_pool);
if (retval < 0)
return retval;
}
for (q = 0; q < tx_rings; q++) {
txconf);
if (retval < 0)
return retval;
}
if (retval < 0)
return retval;
tunnel_udp.udp_port = udp_port;
tunnel_udp.prot_type = RTE_TUNNEL_TYPE_VXLAN;
if (retval < 0)
return retval;
if (retval < 0)
return retval;
RTE_LOG(INFO, PORT,
"Port %u MAC: %02"PRIx8
" %02"PRIx8
" %02"PRIx8
" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
port,
ports_eth_addr[port].addr_bytes[1],
ports_eth_addr[port].addr_bytes[2],
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) {
if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) == 0)
"hardware TSO offload is not supported\n");
}
return 0;
}
static int
{
int ret = 0;
if (rx_decap)
ret = decapsulation(pkt);
return ret;
}
static void
vxlan_tx_process(uint8_t queue_id,
struct rte_mbuf *pkt)
{
if (tx_encap)
encapsulation(pkt, queue_id);
return;
}
int
vxlan_link(
struct vhost_dev *vdev,
struct rte_mbuf *m)
{
int i, ret;
uint64_t portid = vdev->vid;
if (
unlikely(portid >= VXLAN_N_PORTS)) {
"(%d) WARNING: Not configuring device,"
"as already have %d ports for VXLAN.",
vdev->vid, VXLAN_N_PORTS);
return -1;
}
"(%d) WARNING: This device is using an existing"
" MAC address and has not been registered.\n",
vdev->vid);
return -1;
}
vdev->mac_address.addr_bytes[i] =
vxdev.port[portid].vport_mac.addr_bytes[i] =
vxdev.port[portid].peer_mac.addr_bytes[i] = peer_mac[i];
}
memset(&tunnel_filter_conf, 0,
tunnel_filter_conf.filter_type = tep_filter_type[filter_idx];
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;
RTE_ETH_FILTER_TUNNEL,
&tunnel_filter_conf);
if (ret) {
"%d Failed to add device MAC address to cloud filter\n",
vdev->rx_q);
return -1;
}
"(%d) MAC_ADDRESS %02x:%02x:%02x:%02x:%02x:%02x and VNI %d registered\n",
vdev->rx_q,
vdev->mac_address.addr_bytes[0],
vdev->mac_address.addr_bytes[1],
vdev->mac_address.addr_bytes[2],
vdev->mac_address.addr_bytes[3],
vdev->mac_address.addr_bytes[4],
vdev->mac_address.addr_bytes[5],
tenant_id_conf[vdev->rx_q]);
vxdev.port[portid].vport_id = portid;
for (i = 0; i < 4; i++) {
vxdev.port_ip |= vxlan_multicast_ips[portid][i] << (8 * i);
vxdev.port[portid].peer_ip |=
vxlan_overlay_ips[portid][i] << (8 * i);
}
vxdev.out_key = tenant_id_conf[vdev->rx_q];
&app_l2_hdr[portid].d_addr);
ip = &app_ip_hdr[portid];
ip->
dst_addr = vxdev.port[portid].peer_ip;
vdev->ready = DEVICE_RX;
return 0;
}
void
vxlan_unlink(struct vhost_dev *vdev)
{
unsigned i = 0, rx_count;
int ret;
struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
if (vdev->ready == DEVICE_RX) {
memset(&tunnel_filter_conf, 0,
&tunnel_filter_conf.outer_mac);
&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;
RTE_ETH_FILTER_TUNNEL,
&tunnel_filter_conf);
if (ret) {
"%d Failed to add device MAC address to cloud filter\n",
vdev->rx_q);
return;
}
vdev->mac_address.addr_bytes[i] = 0;
(uint16_t)vdev->rx_q,
pkts_burst, MAX_PKT_BURST);
while (rx_count) {
for (i = 0; i < rx_count; i++)
(uint16_t)vdev->rx_q,
pkts_burst, MAX_PKT_BURST);
}
vdev->ready = DEVICE_MAC_LEARNING;
}
}
int
vxlan_tx_pkts(uint16_t port_id, uint16_t queue_id,
struct rte_mbuf **tx_pkts, uint16_t nb_pkts) {
int ret = 0;
uint16_t i;
for (i = 0; i < nb_pkts; i++)
vxlan_tx_process(queue_id, tx_pkts[i]);
return ret;
}
int
vxlan_rx_pkts(
int vid,
struct rte_mbuf **pkts_burst, uint32_t rx_count)
{
uint32_t i = 0;
uint32_t count = 0;
int ret;
for (i = 0; i < rx_count; i++) {
if (enable_stats) {
&dev_statistics[vid].rx_bad_ip_csum,
!= 0);
&dev_statistics[vid].rx_bad_ip_csum,
!= 0);
}
ret = vxlan_rx_process(pkts_burst[i]);
continue;
pkts_valid[count] = pkts_burst[i];
count++;
}
return ret;
}