efx_filter.c revision 49ef7e0638c8b771d8a136eae78b1c0f99acc8e0
/*
* Copyright (c) 2007-2015 Solarflare Communications 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
*
* 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 OWNER 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.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the FreeBSD Project.
*/
#include "efx.h"
#include "efx_impl.h"
#if EFSYS_OPT_FILTER
#if EFSYS_OPT_SIENA
static __checkReturn efx_rc_t
static void
static __checkReturn efx_rc_t
static __checkReturn efx_rc_t
static __checkReturn efx_rc_t
static __checkReturn efx_rc_t
#endif /* EFSYS_OPT_SIENA */
#if EFSYS_OPT_SIENA
static const efx_filter_ops_t __efx_filter_siena_ops = {
siena_filter_init, /* efo_init */
siena_filter_fini, /* efo_fini */
siena_filter_restore, /* efo_restore */
siena_filter_add, /* efo_add */
siena_filter_delete, /* efo_delete */
siena_filter_supported_filters, /* efo_supported_filters */
NULL, /* efo_reconfigure */
};
#endif /* EFSYS_OPT_SIENA */
static const efx_filter_ops_t __efx_filter_ef10_ops = {
ef10_filter_init, /* efo_init */
ef10_filter_fini, /* efo_fini */
ef10_filter_restore, /* efo_restore */
ef10_filter_add, /* efo_add */
ef10_filter_delete, /* efo_delete */
ef10_filter_supported_filters, /* efo_supported_filters */
ef10_filter_reconfigure, /* efo_reconfigure */
};
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
{
}
{
#endif
}
{
goto fail1;
return (0);
return (rc);
}
{
const efx_filter_ops_t *efop;
/* Check that efx_filter_spec_t is 64 bytes. */
#if EFSYS_OPT_SIENA
case EFX_FAMILY_SIENA:
break;
#endif /* EFSYS_OPT_SIENA */
case EFX_FAMILY_HUNTINGTON:
break;
#endif /* EFSYS_OPT_HUNTINGTON */
case EFX_FAMILY_MEDFORD:
break;
#endif /* EFSYS_OPT_MEDFORD */
default:
EFSYS_ASSERT(0);
goto fail1;
}
goto fail2;
return (0);
return (rc);
}
void
{
}
{
goto fail1;
return (0);
return (rc);
}
{
goto fail1;
}
return (0);
return (rc);
}
void
{
EFX_FILTER_FLAG_RX_SCATTER)) == 0);
}
void
{
}
/*
* Specify IPv4 host, transport protocol and port in a filter specification
*/
{
spec->efs_match_flags |=
return (0);
}
/*
* Specify IPv4 hosts, transport protocol and ports in a filter specification
*/
{
spec->efs_match_flags |=
return (0);
}
/*
*/
{
return (EINVAL);
if (vid != EFX_FILTER_SPEC_VID_UNSPEC) {
}
}
return (0);
}
/*
* Specify matching otherwise-unmatched unicast in a filter specification
*/
{
return (0);
}
/*
* Specify matching otherwise-unmatched multicast in a filter specification
*/
{
return (0);
}
#if EFSYS_OPT_SIENA
/*
* "Fudge factors" - difference between programmed value and actual depth.
* Due to pipelined implementation we need to program H/W with a value that
* is larger than the hop limit we want.
*/
#define FILTER_CTL_SRCH_FUDGE_WILD 3
#define FILTER_CTL_SRCH_FUDGE_FULL 1
/*
* Hard maximum hop limit. Hardware will time-out beyond 200-something.
* We also need to avoid infinite loops in efx_filter_search() when the
* table is full.
*/
#define FILTER_CTL_SRCH_MAX 200
static __checkReturn efx_rc_t
{
else
/* Falconsiena only has one RSS context */
gen_spec->efs_rss_context != 0) {
goto fail1;
}
switch (gen_spec->efs_match_flags) {
/* FALLTHROUGH */
goto fail2;
}
if (gen_spec->efs_loc_port == 0 ||
goto fail3;
}
switch (gen_spec->efs_ip_proto) {
case EFX_IPPROTO_TCP:
} else {
}
break;
case EFX_IPPROTO_UDP:
} else {
}
break;
default:
goto fail4;
}
/*
* The filter is constructed in terms of source and destination,
* with the odd wrinkle that the ports are swapped in a UDP
* wildcard filter. We need to convert from local and remote
* addresses (zero for a wildcard).
*/
} else {
}
} else {
}
} else {
} else {
}
}
break;
}
/* FALLTHROUGH */
case EFX_FILTER_MATCH_LOC_MAC:
} else {
}
break;
default:
goto fail5;
}
return (0);
return (rc);
}
/*
* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
* key derived from the n-tuple.
*/
static uint16_t
{
/* First 16 rounds */
/* Last 16 rounds */
return (tmp);
}
/*
* To allow for hash collisions, filter search continues at these
* increments from the first possible entry selected by the hash.
*/
static uint16_t
{
}
static __checkReturn boolean_t
{
}
static void
{
}
static void
{
}
static siena_filter_tbl_id_t
{
switch (type) {
break;
break;
break;
break;
default:
break;
}
return (tbl_id);
}
static void
{
switch (tbl_id) {
break;
break;
break;
break;
default:
break;
}
}
static void
{
}
}
static void
{
}
}
}
/* Build a filter entry and return its n-tuple key. */
static __checkReturn uint32_t
{
switch (siena_filter_tbl_id(type)) {
case EFX_SIENA_FILTER_TBL_RX_IP: {
break;
}
case EFX_SIENA_FILTER_TBL_RX_MAC: {
break;
}
case EFX_SIENA_FILTER_TBL_TX_IP: {
break;
}
case EFX_SIENA_FILTER_TBL_TX_MAC: {
break;
}
default:
return (0);
}
key =
return (key);
}
static __checkReturn efx_rc_t
{
switch (type) {
break;
break;
break;
break;
default:
goto fail1;
}
return (0);
return (rc);
}
static __checkReturn boolean_t
{
return (B_FALSE);
return (B_FALSE);
if ((tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
return (B_FALSE);
return (B_TRUE);
}
static __checkReturn efx_rc_t
__out int *filter_index,
__out unsigned int *depth_required)
{
depth = 1;
for (;;) {
/*
* Return success if entry is used and matches this spec
* or entry is unused and we are trying to insert.
*/
for_insert) {
*depth_required = depth;
return (0);
}
/* Return failure if we reached the maximum search depth */
if (depth == FILTER_CTL_SRCH_MAX)
++depth;
}
}
static void
{
(void) siena_filter_push_entry(enp,
}
}
void
{
int index;
int state;
}
}
static __checkReturn efx_rc_t
{
int tbl_id;
if (!sfp) {
goto fail1;
}
case EFX_FAMILY_SIENA:
break;
default:
goto fail2;
}
unsigned int bitmap_size;
continue;
sizeof (uint32_t));
if (!sftp->sft_bitmap) {
goto fail3;
}
goto fail4;
}
}
return (0);
return (rc);
}
static void
{
return;
unsigned int bitmap_size;
sizeof (uint32_t));
sftp->sft_bitmap);
}
}
}
}
/* Restore filter state after a reset */
static __checkReturn efx_rc_t
{
int filter_idx;
int state;
for (filter_idx = 0;
filter_idx++) {
continue;
goto fail1;
goto fail2;
}
}
return (0);
return (rc);
}
static __checkReturn efx_rc_t
{
int filter_idx;
unsigned int depth;
int state;
goto fail1;
goto fail2;
}
&filter_idx, &depth);
if (rc != 0)
goto fail3;
if (may_replace == B_FALSE) {
goto fail4;
}
}
*saved_sf_spec = sf_spec;
if (tbl_id == EFX_SIENA_FILTER_TBL_TX_IP ||
else
}
filter_idx, &filter);
return (0);
return (rc);
}
static __checkReturn efx_rc_t
{
int filter_idx;
unsigned int depth;
int state;
goto fail1;
&filter_idx, &depth);
if (rc != 0)
goto fail2;
return (0);
return (rc);
}
#define MAX_SUPPORTED 4
static __checkReturn efx_rc_t
{
int index = 0;
goto fail1;
}
rx_matches[index++] =
rx_matches[index++] =
rx_matches[index++] =
}
return (0);
return (rc);
}
#endif /* EFSYS_OPT_SIENA */
#endif /* EFSYS_OPT_FILTER */