/*-
* GPL LICENSE SUMMARY
- *
+ *
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
- *
+ *
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
- *
+ *
* Contact Information:
* Intel Corporation
*/
#include <linux/kthread.h>
#include <linux/delay.h>
-#include <rte_config.h>
#include <exec-env/rte_kni_common.h>
#include <kni_fifo.h>
#include "kni_dev.h"
struct rte_kni_request req;
struct kni_dev *kni = netdev_priv(dev);
- if (kni->lad_dev)
- memcpy(dev->dev_addr, kni->lad_dev->dev_addr, ETH_ALEN);
- else
- /*
- * 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);
memset(&req, 0, sizeof(req));
req.if_up = 1;
ret = kni_net_process_request(kni, &req);
- return (ret == 0 ? req.result : ret);
+ return (ret == 0) ? req.result : ret;
}
static int
req.if_up = 0;
ret = kni_net_process_request(kni, &req);
- return (ret == 0 ? req.result : ret);
+ return (ret == 0) ? req.result : ret;
}
/*
{
unsigned ret;
uint32_t len;
- unsigned i, num, num_rq, num_fq;
+ unsigned i, num_rx, num_fq;
struct rte_kni_mbuf *kva;
struct rte_kni_mbuf *va[MBUF_BURST_SZ];
void * data_kva;
struct sk_buff *skb;
struct net_device *dev = kni->net_dev;
- /* Get the number of entries in rx_q */
- num_rq = kni_fifo_count(kni->rx_q);
-
/* Get the number of free entries in free_q */
num_fq = kni_fifo_free_count(kni->free_q);
-
- /* Calculate the number of entries to dequeue in rx_q */
- num = min(num_rq, num_fq);
- num = min(num, (unsigned)MBUF_BURST_SZ);
-
- /* Return if no entry in rx_q and no free entry in free_q */
- if (num == 0)
+ if (num_fq == 0) {
+ /* No room on the free_q, bail out */
return;
+ }
+
+ /* Calculate the number of entries to dequeue from rx_q */
+ num_rx = min(num_fq, (unsigned)MBUF_BURST_SZ);
/* Burst dequeue from rx_q */
- ret = kni_fifo_get(kni->rx_q, (void **)va, num);
- if (ret == 0)
- return; /* Failing should not happen */
+ num_rx = kni_fifo_get(kni->rx_q, (void **)va, num_rx);
+ if (num_rx == 0)
+ return;
/* Transfer received packets to netif */
- for (i = 0; i < num; i++) {
+ for (i = 0; i < num_rx; i++) {
kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva;
len = kva->data_len;
- data_kva = kva->data - kni->mbuf_va + kni->mbuf_kva;
+ data_kva = kva->buf_addr + kva->data_off - kni->mbuf_va
+ + kni->mbuf_kva;
skb = dev_alloc_skb(len + 2);
if (!skb) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
/* Call netif interface */
- netif_receive_skb(skb);
+ netif_rx_ni(skb);
/* Update statistics */
kni->stats.rx_bytes += len;
}
/* Burst enqueue mbufs into free_q */
- ret = kni_fifo_put(kni->free_q, (void **)va, num);
- if (ret != num)
+ ret = kni_fifo_put(kni->free_q, (void **)va, num_rx);
+ if (ret != num_rx)
/* Failing should not happen */
KNI_ERR("Fail to enqueue entries into free_q\n");
}
for (i = 0; i < num; i++) {
kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva;
len = kva->pkt_len;
- data_kva = kva->data - kni->mbuf_va +
- kni->mbuf_kva;
+ data_kva = kva->buf_addr + kva->data_off -
+ kni->mbuf_va + kni->mbuf_kva;
alloc_kva = (void *)alloc_va[i] - kni->mbuf_va +
kni->mbuf_kva;
- alloc_data_kva = alloc_kva->data - kni->mbuf_va +
- kni->mbuf_kva;
+ alloc_data_kva = alloc_kva->buf_addr +
+ alloc_kva->data_off - kni->mbuf_va +
+ kni->mbuf_kva;
memcpy(alloc_data_kva, data_kva, len);
alloc_kva->pkt_len = len;
alloc_kva->data_len = len;
for (i = 0; i < num; i++) {
kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva;
len = kva->data_len;
- data_kva = kva->data - kni->mbuf_va + kni->mbuf_kva;
+ data_kva = kva->buf_addr + kva->data_off - kni->mbuf_va +
+ kni->mbuf_kva;
skb = dev_alloc_skb(len + 2);
if (skb == NULL)
kni_net_tx(struct sk_buff *skb, struct net_device *dev)
{
struct kni_dev *kni = netdev_priv(dev);
-
+
dev_kfree_skb(skb);
kni->stats.tx_dropped++;
-
+
return NETDEV_TX_OK;
}
#else
void *data_kva;
pkt_kva = (void *)pkt_va - kni->mbuf_va + kni->mbuf_kva;
- data_kva = pkt_kva->data - kni->mbuf_va + kni->mbuf_kva;
+ data_kva = pkt_kva->buf_addr + pkt_kva->data_off - kni->mbuf_va
+ + kni->mbuf_kva;
len = skb->len;
memcpy(data_kva, skb->data, len);
return 0;
}
+static void
+kni_net_set_rx_mode(struct net_device *dev)
+{
+}
+
static int
kni_net_change_mtu(struct net_device *dev, int new_mtu)
{
if (ret == 0 && req.result == 0)
dev->mtu = new_mtu;
- return (ret == 0 ? req.result : ret);
+ return (ret == 0) ? req.result : ret;
}
/*
memcpy(eth->h_dest, daddr ? daddr : dev->dev_addr, dev->addr_len);
eth->h_proto = htons(type);
- return (dev->hard_header_len);
+ return dev->hard_header_len;
}
/*
* Re-fill the eth header
*/
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
static int
kni_net_rebuild_header(struct sk_buff *skb)
{
return 0;
}
+#endif /* < 4.1.0 */
+
+/**
+ * kni_net_set_mac - Change the Ethernet Address of the KNI NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int kni_net_set_mac(struct net_device *netdev, void *p)
+{
+ struct sockaddr *addr = p;
+ if (!is_valid_ether_addr((unsigned char *)(addr->sa_data)))
+ return -EADDRNOTAVAIL;
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ return 0;
+}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+static int kni_net_change_carrier(struct net_device *dev, bool new_carrier)
+{
+ if (new_carrier)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
+ return 0;
+}
+#endif
static const struct header_ops kni_net_header_ops = {
.create = kni_net_header,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0))
.rebuild = kni_net_rebuild_header,
+#endif /* < 4.1.0 */
.cache = NULL, /* disable caching */
};
.ndo_start_xmit = kni_net_tx,
.ndo_change_mtu = kni_net_change_mtu,
.ndo_do_ioctl = kni_net_ioctl,
+ .ndo_set_rx_mode = kni_net_set_rx_mode,
.ndo_get_stats = kni_net_stats,
.ndo_tx_timeout = kni_net_tx_timeout,
+ .ndo_set_mac_address = kni_net_set_mac,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+ .ndo_change_carrier = kni_net_change_carrier,
+#endif
};
void