--- /root/base/nopenvswitch-2.4.0.1/DPDK/lib/librte_kni/rte_kni.c    2015-04-03 10:13:45.000000000 -0400
+++ /root/base/openvswitch-2.4.0.1/DPDK/lib/librte_kni/rte_kni.c     2016-03-01 09:02:21.449863228 -0500
@@ -432,7 +432,7 @@
    dev_info.sync_va = mz->addr;
    dev_info.sync_phys = mz->phys_addr;
-
+        memset(mz_name,0, sizeof(mz_name));
    /* MBUF mempool */
    snprintf(mz_name, sizeof(mz_name), RTE_MEMPOOL_OBJ_NAME,
          pktmbuf_pool->name);
@@ -749,3 +749,8 @@
    close(kni_fd);
    kni_fd = -1;
}
+int
+rte_kni_get_fd(void)
+{
+    return kni_fd;
+}
--- /root/base/nopenvswitch-2.4.0.1/DPDK/lib/librte_kni/rte_kni.h    2015-04-03 10:13:45.000000000 -0400
+++ /root/base/openvswitch-2.4.0.1/DPDK/lib/librte_kni/rte_kni.h     2016-03-01 09:04:26.128870730 -0500
@@ -297,6 +297,15 @@
  *   void
  */
extern void rte_kni_close(void);
+/**
+ *  get fd for KNI device.
+ *
+ *  @param void
+ *
+ *  @return
+ *   int
+ */
+extern int rte_kni_get_fd(void);
 #ifdef __cplusplus
}
--- /root/base/nopenvswitch-2.4.0.1/DPDK/lib/librte_eal/linuxapp/kni/kni_net.c     2015-04-03 10:13:45.000000000 -0400
+++ /root/base/openvswitch-2.4.0.1/DPDK/lib/librte_eal/linuxapp/kni/kni_net.c     2016-03-01 09:43:46.935012781 -0500
@@ -72,12 +72,13 @@
     if (kni->lad_dev)
          memcpy(dev->dev_addr, kni->lad_dev->dev_addr, ETH_ALEN);
-    else
+    else if(strlen(dev->dev_addr)==0){
          /*
           * Generate random mac address. eth_random_addr() is the newer
           * version of generating mac address in linux kernel.
           */
          random_ether_addr(dev->dev_addr);
+    }
     netif_start_queue(dev);
--- /root/base/nopenvswitch-2.4.0.1/openvswitch-2.4.0/lib/netdev-dpdk.c     2015-08-20 20:18:21.386479276 -0400
+++ /root/base/openvswitch-2.4.0.1/openvswitch-2.4.0/lib/netdev-dpdk.c     2016-03-01 10:01:11.569075636 -0500
@@ -53,6 +53,7 @@
#include "rte_config.h"
#include "rte_mbuf.h"
#include "rte_virtio_net.h"
+#include <rte_kni.h>
 VLOG_DEFINE_THIS_MODULE(dpdk);
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
@@ -62,6 +63,13 @@
#define OVS_CACHE_LINE_SIZE CACHE_LINE_SIZE
#define OVS_VPORT_DPDK "ovs_dpdk"
+#define MAX_PACKET_SZ               2048
+#define NUM_KNI_INTERFACES          16
+#define PORT_VETH_RX_BURST_SIZE     32
+#define PORT_VETH_TX_BURST_SIZE     32
+#define VETH_RETRY_NUM         4
+#define VETH_RETRY_DELAY_US    10
+
/*
  * need to reserve tons of extra space in the mbufs so we can align the
  * DMA addresses to 4KB.
@@ -130,6 +138,7 @@
enum dpdk_dev_type {
     DPDK_DEV_ETH = 0,
     DPDK_DEV_VHOST = 1,
+    DPDK_DEV_KNI = 2
};
 static int rte_eal_init_ret = ENODEV;
@@ -223,7 +232,10 @@
     /* virtio-net structure for vhost device */
     OVSRCU_TYPE(struct virtio_net *) virtio_dev;
-
+
+    /* kni structure for veth device */
+    struct rte_kni *veth;
+
     /* Identifier used to distinguish vhost devices from each other */
     char vhost_id[PATH_MAX];
@@ -235,6 +247,7 @@
     struct netdev_rxq up;
     int port_id;
};
+int kni_dpdk_set_mac(struct netdev_dpdk *);
 static bool thread_is_pmd(void);
@@ -535,7 +548,49 @@
     dev->flags = NETDEV_UP | NETDEV_PROMISC;
     return 0;
}
+static int
+dpdk_veth_dev_init(struct netdev_dpdk *dev) OVS_REQUIRES(dpdk_mutex)
+{
+    int err=0;
+    struct rte_kni *veth = NULL;
+    struct rte_kni_conf conf;
+    static int port_id = 1;
+
+    if (rte_kni_get(dev->up.name)){
+        VLOG_ERR("Kni interface %s already exists",dev->up.name);
+        return EAGAIN;
+    }
+           /* invoke init before rte_kni_alloc.Currently hardcoded the num of kni interfaces as 2  */
+     if (rte_kni_get_fd() == -1)
+         rte_kni_init(NUM_KNI_INTERFACES);
+
+     kni_dpdk_set_mac(dev);
+        /* Clear conf at first */
+     memset(&conf, 0, sizeof(conf));
+     memcpy(conf.name, dev->up.name, RTE_KNI_NAMESIZE);
+     conf.group_id = (uint16_t)port_id; /* currently group id is hardcoded */
+     conf.mbuf_size = MAX_PACKET_SZ;
+
+     veth = rte_kni_alloc(dev->dpdk_mp->mp, &conf, NULL);
+     if (veth !=  NULL){
+        port_id ++; /* increment the port id for the next kni interface */
+        dev->veth = veth;
+     }
+     else
+        err = ENOMEM;
+
+     return err;
+}
+int kni_dpdk_set_mac(struct netdev_dpdk *dev)
+{
+        struct ether_addr addr;
+        if(!is_zero_ether_addr(&addr)){
+                eth_random_addr(&addr);
+                memcpy(dev->hwaddr, addr.addr_bytes,ETH_ADDR_LEN);
+        }
+        return 0;
+}
static struct netdev_dpdk *
netdev_dpdk_cast(const struct netdev *netdev)
{
@@ -619,6 +674,12 @@
             goto unlock;
         }
     }
+    else if(type == DPDK_DEV_KNI) {
+        err = dpdk_veth_dev_init(netdev);
+        if (err) {
+            goto unlock;
+        }
+    }
     list_push_back(&dpdk_list, &netdev->list_node);
@@ -693,7 +754,25 @@
     ovs_mutex_unlock(&dpdk_mutex);
     return err;
}
+static int
+netdev_dpdk_veth_construct(struct netdev *netdev_)
+{
+    struct netdev_dpdk *netdev = netdev_dpdk_cast(netdev_);
+    int err=0;
+
+    if (rte_eal_init_ret) {
+        return rte_eal_init_ret;
+    }
+
+    ovs_mutex_lock(&dpdk_mutex);
+    err = netdev_dpdk_init(netdev_, -1, DPDK_DEV_KNI);
+    ovs_mutex_unlock(&dpdk_mutex);
+    rte_spinlock_init(&netdev->vhost_tx_lock); /* using same structure host_tx_lock for kni */
+
+    return err;
+
+}
static int
netdev_dpdk_construct(struct netdev *netdev)
{
@@ -748,7 +827,23 @@
     dpdk_mp_put(dev->dpdk_mp);
     ovs_mutex_unlock(&dpdk_mutex);
}
+static void
+netdev_dpdk_veth_destruct(struct netdev *netdev_)
+{
+    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev_);
+    ovs_mutex_lock(&dev->mutex);
+    if (rte_kni_release(dev->veth)) {
+        VLOG_ERR("Failed to release KNI interface");
+        return;
+    }
+    ovs_mutex_unlock(&dev->mutex);
+
+    ovs_mutex_lock(&dpdk_mutex);
+    list_remove(&dev->list_node);
+    dpdk_mp_put(dev->dpdk_mp);
+    ovs_mutex_unlock(&dpdk_mutex);
+}
static void
netdev_dpdk_dealloc(struct netdev *netdev_)
{
@@ -972,7 +1067,36 @@
     *c = (int) nb_rx;
     return 0;
}
+static int
+netdev_dpdk_veth_rxq_recv(struct netdev_rxq *rxq_,
+                           struct dp_packet **packets, int *c)
+{
+    struct netdev_rxq_dpdk *rx = netdev_rxq_dpdk_cast(rxq_);
+    struct netdev *netdev = rx->up.netdev;
+    struct netdev_dpdk *veth_dev = netdev_dpdk_cast(netdev);
+    uint16_t nb_rx = 0;
+    struct rte_kni *veth = NULL;
+    veth = veth_dev->veth;
+
+    if (veth != NULL)
+    {
+      /* receive and free */
+        nb_rx =  rte_kni_rx_burst(veth, (struct rte_mbuf **)packets, PORT_VETH_RX_BURST_SIZE);
+ /* handle callbacks (i.e. ifconfig) before we return */
+        rte_kni_handle_request(veth);
+        if (!nb_rx) {
+           return EAGAIN;
+     }
+     rte_spinlock_lock(&veth_dev->stats_lock);
+     veth_dev->stats.rx_packets += (uint64_t)nb_rx;
+     rte_spinlock_unlock(&veth_dev->stats_lock);
+
+     *c = (int) nb_rx;
+     return 0;
+  }
+  return EAGAIN;
+}
static int
netdev_dpdk_rxq_recv(struct netdev_rxq *rxq_, struct dp_packet **packets,
                      int *c)
@@ -1191,6 +1315,62 @@
     }
     return 0;
}
+static int
+netdev_dpdk_veth_send(struct netdev *netdev_, int qid OVS_UNUSED, struct dp_packet **pkts,
+                 int cnt, bool may_steal)
+{
+        struct netdev_dpdk *netdev = netdev_dpdk_cast(netdev_);
+        struct rte_kni *veth = NULL;
+        struct rte_mbuf **cur_pkts =  (struct rte_mbuf **)pkts;
+        unsigned int tx_pkts = 0, dropped_pkts = 0, i;
+
+        if (!thread_is_pmd()) {
+            ovs_mutex_lock(&nonpmd_mempool_mutex);
+        }
+        veth = netdev->veth;
+        if (veth == NULL)
+        {
+            rte_spinlock_lock(&netdev->stats_lock);
+            netdev->stats.tx_dropped+= cnt;
+            rte_spinlock_unlock(&netdev->stats_lock);
+            goto out;
+
+        }
+        rte_spinlock_lock(&netdev->vhost_tx_lock);
+
+       for (i=0;i<cnt;i++)
+       {
+           if (cur_pkts[i]->data_off < RTE_PKTMBUF_HEADROOM)
+               ++dropped_pkts;
+
+           else if (rte_kni_tx_burst(veth,
+                           (struct rte_mbuf **) &cur_pkts[i], 1))
+                ++tx_pkts;
+           else
+                ++dropped_pkts;
+
+       }
+        rte_spinlock_unlock(&netdev->vhost_tx_lock);
+
+         /* statistics for the no of packets sent */
+        rte_spinlock_lock(&netdev->stats_lock);
+        netdev->stats.tx_packets += tx_pkts;
+        netdev->stats.tx_dropped += dropped_pkts;
+        rte_spinlock_unlock(&netdev->stats_lock);
+
+        if (!thread_is_pmd()) {
+            ovs_mutex_unlock(&nonpmd_mempool_mutex);
+        }
+
+out:    if (may_steal) {
+        int i;
+        for (i = 0; i < cnt; i++) {
+            dp_packet_delete(pkts[i]);
+        }
+        }
+        return 0;
+
+}
 static inline void
netdev_dpdk_send__(struct netdev_dpdk *dev, int qid,
@@ -1394,7 +1574,45 @@
     return 0;
}
+static int
+netdev_dpdk_veth_get_stats(const struct netdev *netdev,
+                            struct netdev_stats *stats)
+{
+    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+
+    ovs_mutex_lock(&dev->mutex);
+    memset(stats, 0, sizeof(*stats));
+    /* Unsupported Stats */
+    stats->rx_errors = UINT64_MAX;
+    stats->tx_errors = UINT64_MAX;
+    stats->multicast = UINT64_MAX;
+    stats->collisions = UINT64_MAX;
+    stats->rx_crc_errors = UINT64_MAX;
+    stats->rx_fifo_errors = UINT64_MAX;
+    stats->rx_frame_errors = UINT64_MAX;
+    stats->rx_length_errors = UINT64_MAX;
+    stats->rx_missed_errors = UINT64_MAX;
+    stats->rx_over_errors = UINT64_MAX;
+    stats->tx_aborted_errors = UINT64_MAX;
+    stats->tx_carrier_errors = UINT64_MAX;
+    stats->tx_errors = UINT64_MAX;
+    stats->tx_fifo_errors = UINT64_MAX;
+    stats->tx_heartbeat_errors = UINT64_MAX;
+    stats->tx_window_errors = UINT64_MAX;
+    stats->rx_bytes += UINT64_MAX;
+    stats->rx_dropped += UINT64_MAX;
+    stats->tx_bytes += UINT64_MAX;
+
+    rte_spinlock_lock(&dev->stats_lock);
+    /* Supported Stats */
+    stats->rx_packets += dev->stats.rx_packets;
+    stats->tx_packets += dev->stats.tx_packets;
+    stats->tx_dropped += dev->stats.tx_dropped;
+    rte_spinlock_unlock(&dev->stats_lock);
+    ovs_mutex_unlock(&dev->mutex);
+    return 0;
+}
static int
netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
{
@@ -2177,6 +2395,20 @@
         NULL,
         netdev_dpdk_vhost_rxq_recv);
+static const struct netdev_class dpdk_kni_class =
+    NETDEV_DPDK_CLASS(
+        "dpdkkni",
+        NULL,
+        netdev_dpdk_veth_construct,
+        netdev_dpdk_veth_destruct,
+        NULL,
+        netdev_dpdk_veth_send,
+        NULL,
+        netdev_dpdk_veth_get_stats,
+        NULL,
+        NULL,
+        netdev_dpdk_veth_rxq_recv);
+
void
netdev_dpdk_register(void)
{
@@ -2195,6 +2427,7 @@
#else
         netdev_register_provider(&dpdk_vhost_user_class);
#endif
+    netdev_register_provider(&dpdk_kni_class);
         ovsthread_once_done(&once);
     }
}
--- /root/base/nopenvswitch-2.4.0.1/openvswitch-2.4.0/lib/netdev.c   2015-08-20 20:18:21.430479276 -0400
+++ /root/base/openvswitch-2.4.0.1/openvswitch-2.4.0/lib/netdev.c    2016-03-01 09:41:53.295005943 -0500
@@ -112,7 +112,8 @@
     return (!strcmp(netdev->netdev_class->type, "dpdk") ||
             !strcmp(netdev->netdev_class->type, "dpdkr") ||
             !strcmp(netdev->netdev_class->type, "dpdkvhostcuse") ||
-            !strcmp(netdev->netdev_class->type, "dpdkvhostuser"));
+            !strcmp(netdev->netdev_class->type, "dpdkvhostuser")||
+            !strcmp(netdev->netdev_class->type, "dpdkkni"));
}
 static void
@@ -661,6 +662,7 @@
