-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Sujith Sankar <ssujith@cisco.com> Acked-by: David Marchand <david.marchand@6wind.com> Acked-by: Neil Horman <nhorman@tuxdriver.com>
- Loading branch information
Sujith Sankar
authored and
Thomas Monjalon
committed
Nov 26, 2014
1 parent
9913fbb
commit fefed3d
Showing
7 changed files
with
2,804 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/* | ||
* Copyright 2008-2014 Cisco Systems, Inc. All rights reserved. | ||
* Copyright 2007 Nuova Systems, Inc. All rights reserved. | ||
* | ||
* Copyright (c) 2014, Cisco Systems, Inc. | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions | ||
* are met: | ||
* | ||
* 1. Redistributions of source code must retain the above copyright | ||
* notice, this list of conditions and the following disclaimer. | ||
* | ||
* 2. Redistributions in binary form must reproduce the above copyright | ||
* notice, this list of conditions and the following disclaimer in | ||
* the documentation and/or other materials provided with the | ||
* distribution. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | ||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
* POSSIBILITY OF SUCH DAMAGE. | ||
* | ||
*/ | ||
#ident "$Id$" | ||
|
||
#ifndef _ENIC_H_ | ||
#define _ENIC_H_ | ||
|
||
#include "vnic_enet.h" | ||
#include "vnic_dev.h" | ||
#include "vnic_wq.h" | ||
#include "vnic_rq.h" | ||
#include "vnic_cq.h" | ||
#include "vnic_intr.h" | ||
#include "vnic_stats.h" | ||
#include "vnic_nic.h" | ||
#include "vnic_rss.h" | ||
#include "enic_res.h" | ||
|
||
#define DRV_NAME "enic_pmd" | ||
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Poll-mode Driver" | ||
#define DRV_VERSION "1.0.0.4" | ||
#define DRV_COPYRIGHT "Copyright 2008-2014 Cisco Systems, Inc" | ||
|
||
#define ENIC_WQ_MAX 8 | ||
#define ENIC_RQ_MAX 8 | ||
#define ENIC_CQ_MAX (ENIC_WQ_MAX + ENIC_RQ_MAX) | ||
#define ENIC_INTR_MAX (ENIC_CQ_MAX + 2) | ||
|
||
#define VLAN_ETH_HLEN 18 | ||
|
||
#define ENICPMD_SETTING(enic, f) ((enic->config.flags & VENETF_##f) ? 1 : 0) | ||
|
||
#define ENICPMD_BDF_LENGTH 13 /* 0000:00:00.0'\0' */ | ||
#define PKT_TX_TCP_UDP_CKSUM 0x6000 | ||
#define ENIC_CALC_IP_CKSUM 1 | ||
#define ENIC_CALC_TCP_UDP_CKSUM 2 | ||
#define ENIC_MAX_MTU 9000 | ||
#define PAGE_SIZE 4096 | ||
#define PAGE_ROUND_UP(x) \ | ||
((((unsigned long)(x)) + PAGE_SIZE-1) & (~(PAGE_SIZE-1))) | ||
|
||
#define ENICPMD_VFIO_PATH "/dev/vfio/vfio" | ||
/*#define ENIC_DESC_COUNT_MAKE_ODD (x) do{if ((~(x)) & 1) { (x)--; } }while(0)*/ | ||
|
||
#define PCI_DEVICE_ID_CISCO_VIC_ENET 0x0043 /* ethernet vnic */ | ||
#define PCI_DEVICE_ID_CISCO_VIC_ENET_VF 0x0071 /* enet SRIOV VF */ | ||
|
||
|
||
#define ENICPMD_FDIR_MAX 64 | ||
|
||
struct enic_fdir_node { | ||
struct rte_fdir_filter filter; | ||
u16 fltr_id; | ||
u16 rq_index; | ||
}; | ||
|
||
struct enic_fdir { | ||
struct rte_eth_fdir stats; | ||
struct rte_hash *hash; | ||
struct enic_fdir_node *nodes[ENICPMD_FDIR_MAX]; | ||
}; | ||
|
||
/* Per-instance private data structure */ | ||
struct enic { | ||
struct enic *next; | ||
struct rte_pci_device *pdev; | ||
struct vnic_enet_config config; | ||
struct vnic_dev_bar bar0; | ||
struct vnic_dev *vdev; | ||
|
||
struct rte_eth_dev *rte_dev; | ||
struct enic_fdir fdir; | ||
char bdf_name[ENICPMD_BDF_LENGTH]; | ||
int dev_fd; | ||
int iommu_group_fd; | ||
int iommu_groupid; | ||
int eventfd; | ||
u_int8_t mac_addr[ETH_ALEN]; | ||
pthread_t err_intr_thread; | ||
int promisc; | ||
int allmulti; | ||
int ig_vlan_strip_en; | ||
int link_status; | ||
u8 hw_ip_checksum; | ||
|
||
unsigned int flags; | ||
unsigned int priv_flags; | ||
|
||
/* work queue */ | ||
struct vnic_wq wq[ENIC_WQ_MAX]; | ||
unsigned int wq_count; | ||
|
||
/* receive queue */ | ||
struct vnic_rq rq[ENIC_RQ_MAX]; | ||
unsigned int rq_count; | ||
|
||
/* completion queue */ | ||
struct vnic_cq cq[ENIC_CQ_MAX]; | ||
unsigned int cq_count; | ||
|
||
/* interrupt resource */ | ||
struct vnic_intr intr; | ||
unsigned int intr_count; | ||
}; | ||
|
||
static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq) | ||
{ | ||
return rq; | ||
} | ||
|
||
static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq) | ||
{ | ||
return enic->rq_count + wq; | ||
} | ||
|
||
static inline unsigned int enic_msix_err_intr(struct enic *enic) | ||
{ | ||
return 0; | ||
} | ||
|
||
static inline struct enic *pmd_priv(struct rte_eth_dev *eth_dev) | ||
{ | ||
return (struct enic *)eth_dev->data->dev_private; | ||
} | ||
|
||
#endif /* _ENIC_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
/* | ||
* Copyright 2008-2014 Cisco Systems, Inc. All rights reserved. | ||
* Copyright 2007 Nuova Systems, Inc. All rights reserved. | ||
* | ||
* Copyright (c) 2014, Cisco Systems, Inc. | ||
* All rights reserved. | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions | ||
* are met: | ||
* | ||
* 1. Redistributions of source code must retain the above copyright | ||
* notice, this list of conditions and the following disclaimer. | ||
* | ||
* 2. Redistributions in binary form must reproduce the above copyright | ||
* notice, this list of conditions and the following disclaimer in | ||
* the documentation and/or other materials provided with the | ||
* distribution. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | ||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | ||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
* POSSIBILITY OF SUCH DAMAGE. | ||
* | ||
*/ | ||
#ident "$Id$" | ||
|
||
#include <libgen.h> | ||
|
||
#include <rte_ethdev.h> | ||
#include <rte_malloc.h> | ||
#include <rte_hash.h> | ||
#include <rte_byteorder.h> | ||
|
||
#include "enic_compat.h" | ||
#include "enic.h" | ||
#include "wq_enet_desc.h" | ||
#include "rq_enet_desc.h" | ||
#include "cq_enet_desc.h" | ||
#include "vnic_enet.h" | ||
#include "vnic_dev.h" | ||
#include "vnic_wq.h" | ||
#include "vnic_rq.h" | ||
#include "vnic_cq.h" | ||
#include "vnic_intr.h" | ||
#include "vnic_nic.h" | ||
|
||
#ifdef RTE_MACHINE_CPUFLAG_SSE4_2 | ||
#include <rte_hash_crc.h> | ||
#define DEFAULT_HASH_FUNC rte_hash_crc | ||
#else | ||
#include <rte_jhash.h> | ||
#define DEFAULT_HASH_FUNC rte_jhash | ||
#endif | ||
|
||
#define SOCKET_0 0 | ||
#define ENICPMD_CLSF_HASH_ENTRIES ENICPMD_FDIR_MAX | ||
#define ENICPMD_CLSF_BUCKET_ENTRIES 4 | ||
|
||
int enic_fdir_del_fltr(struct enic *enic, struct rte_fdir_filter *params) | ||
{ | ||
int32_t pos; | ||
struct enic_fdir_node *key; | ||
/* See if the key is in the table */ | ||
pos = rte_hash_del_key(enic->fdir.hash, params); | ||
switch (pos) { | ||
case -EINVAL: | ||
case -ENOENT: | ||
enic->fdir.stats.f_remove++; | ||
return -EINVAL; | ||
default: | ||
/* The entry is present in the table */ | ||
key = enic->fdir.nodes[pos]; | ||
|
||
/* Delete the filter */ | ||
vnic_dev_classifier(enic->vdev, CLSF_DEL, | ||
&key->fltr_id, NULL); | ||
rte_free(key); | ||
enic->fdir.nodes[pos] = NULL; | ||
enic->fdir.stats.free++; | ||
enic->fdir.stats.remove++; | ||
break; | ||
} | ||
return 0; | ||
} | ||
|
||
int enic_fdir_add_fltr(struct enic *enic, struct rte_fdir_filter *params, | ||
u16 queue, u8 drop) | ||
{ | ||
struct enic_fdir_node *key; | ||
struct filter fltr = {0}; | ||
int32_t pos; | ||
u8 do_free = 0; | ||
u16 old_fltr_id = 0; | ||
|
||
if (!enic->fdir.hash || params->vlan_id || !params->l4type || | ||
(RTE_FDIR_IPTYPE_IPV6 == params->iptype) || | ||
(RTE_FDIR_L4TYPE_SCTP == params->l4type) || | ||
params->flex_bytes || drop) { | ||
enic->fdir.stats.f_add++; | ||
return -ENOTSUP; | ||
} | ||
|
||
/* See if the key is already there in the table */ | ||
pos = rte_hash_del_key(enic->fdir.hash, params); | ||
switch (pos) { | ||
case -EINVAL: | ||
enic->fdir.stats.f_add++; | ||
return -EINVAL; | ||
case -ENOENT: | ||
/* Add a new classifier entry */ | ||
if (!enic->fdir.stats.free) { | ||
enic->fdir.stats.f_add++; | ||
return -ENOSPC; | ||
} | ||
key = (struct enic_fdir_node *)rte_zmalloc( | ||
"enic_fdir_node", | ||
sizeof(struct enic_fdir_node), 0); | ||
if (!key) { | ||
enic->fdir.stats.f_add++; | ||
return -ENOMEM; | ||
} | ||
break; | ||
default: | ||
/* The entry is already present in the table. | ||
* Check if there is a change in queue | ||
*/ | ||
key = enic->fdir.nodes[pos]; | ||
enic->fdir.nodes[pos] = NULL; | ||
if (unlikely(key->rq_index == queue)) { | ||
/* Nothing to be done */ | ||
pos = rte_hash_add_key(enic->fdir.hash, params); | ||
enic->fdir.nodes[pos] = key; | ||
enic->fdir.stats.f_add++; | ||
dev_warning(enic, | ||
"FDIR rule is already present\n"); | ||
return 0; | ||
} | ||
|
||
if (likely(enic->fdir.stats.free)) { | ||
/* Add the filter and then delete the old one. | ||
* This is to avoid packets from going into the | ||
* default queue during the window between | ||
* delete and add | ||
*/ | ||
do_free = 1; | ||
old_fltr_id = key->fltr_id; | ||
} else { | ||
/* No free slots in the classifier. | ||
* Delete the filter and add the modified one later | ||
*/ | ||
vnic_dev_classifier(enic->vdev, CLSF_DEL, | ||
&key->fltr_id, NULL); | ||
enic->fdir.stats.free++; | ||
} | ||
|
||
break; | ||
} | ||
|
||
key->filter = *params; | ||
key->rq_index = queue; | ||
|
||
fltr.type = FILTER_IPV4_5TUPLE; | ||
fltr.u.ipv4.src_addr = rte_be_to_cpu_32(params->ip_src.ipv4_addr); | ||
fltr.u.ipv4.dst_addr = rte_be_to_cpu_32(params->ip_dst.ipv4_addr); | ||
fltr.u.ipv4.src_port = rte_be_to_cpu_16(params->port_src); | ||
fltr.u.ipv4.dst_port = rte_be_to_cpu_16(params->port_dst); | ||
|
||
if (RTE_FDIR_L4TYPE_TCP == params->l4type) | ||
fltr.u.ipv4.protocol = PROTO_TCP; | ||
else | ||
fltr.u.ipv4.protocol = PROTO_UDP; | ||
|
||
fltr.u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE; | ||
|
||
if (!vnic_dev_classifier(enic->vdev, CLSF_ADD, &queue, &fltr)) { | ||
key->fltr_id = queue; | ||
} else { | ||
dev_err(enic, "Add classifier entry failed\n"); | ||
enic->fdir.stats.f_add++; | ||
rte_free(key); | ||
return -1; | ||
} | ||
|
||
if (do_free) | ||
vnic_dev_classifier(enic->vdev, CLSF_DEL, &old_fltr_id, NULL); | ||
else{ | ||
enic->fdir.stats.free--; | ||
enic->fdir.stats.add++; | ||
} | ||
|
||
pos = rte_hash_add_key(enic->fdir.hash, (void *)key); | ||
enic->fdir.nodes[pos] = key; | ||
return 0; | ||
} | ||
|
||
void enic_clsf_destroy(struct enic *enic) | ||
{ | ||
u32 index; | ||
struct enic_fdir_node *key; | ||
/* delete classifier entries */ | ||
for (index = 0; index < ENICPMD_FDIR_MAX; index++) { | ||
key = enic->fdir.nodes[index]; | ||
if (key) { | ||
vnic_dev_classifier(enic->vdev, CLSF_DEL, | ||
&key->fltr_id, NULL); | ||
rte_free(key); | ||
} | ||
} | ||
|
||
if (enic->fdir.hash) { | ||
rte_hash_free(enic->fdir.hash); | ||
enic->fdir.hash = NULL; | ||
} | ||
} | ||
|
||
int enic_clsf_init(struct enic *enic) | ||
{ | ||
struct rte_hash_parameters hash_params = { | ||
.name = "enicpmd_clsf_hash", | ||
.entries = ENICPMD_CLSF_HASH_ENTRIES, | ||
.bucket_entries = ENICPMD_CLSF_BUCKET_ENTRIES, | ||
.key_len = sizeof(struct rte_fdir_filter), | ||
.hash_func = DEFAULT_HASH_FUNC, | ||
.hash_func_init_val = 0, | ||
.socket_id = SOCKET_0, | ||
}; | ||
|
||
enic->fdir.hash = rte_hash_create(&hash_params); | ||
memset(&enic->fdir.stats, 0, sizeof(enic->fdir.stats)); | ||
enic->fdir.stats.free = ENICPMD_FDIR_MAX; | ||
return (NULL == enic->fdir.hash); | ||
} |
Oops, something went wrong.