static __checkReturn efx_rc_t
siena_filter_supported_filters(
- __in efx_nic_t *enp,
- __out uint32_t *list,
- __out size_t *length);
+ __in efx_nic_t *enp,
+ __out_ecount(buffer_length) uint32_t *buffer,
+ __in size_t buffer_length,
+ __out size_t *list_lengthp);
#endif /* EFSYS_OPT_SIENA */
const efx_filter_ops_t *efop;
efx_rc_t rc;
- /* Check that efx_filter_spec_t is 64 bytes. */
- EFX_STATIC_ASSERT(sizeof (efx_filter_spec_t) == 64);
-
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_FILTER));
enp->en_mod_flags &= ~EFX_MOD_FILTER;
}
+/*
+ * Query the possible combinations of match flags which can be filtered on.
+ * These are returned as a list, of which each 32 bit element is a bitmask
+ * formed of EFX_FILTER_MATCH flags.
+ *
+ * The combinations are ordered in priority from highest to lowest.
+ *
+ * If the provided buffer is too short to hold the list, the call with fail with
+ * ENOSPC and *list_lengthp will be set to the buffer length required.
+ */
__checkReturn efx_rc_t
efx_filter_supported_filters(
- __in efx_nic_t *enp,
- __out uint32_t *list,
- __out size_t *length)
+ __in efx_nic_t *enp,
+ __out_ecount(buffer_length) uint32_t *buffer,
+ __in size_t buffer_length,
+ __out size_t *list_lengthp)
{
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
EFSYS_ASSERT(enp->en_efop->efo_supported_filters != NULL);
- if ((rc = enp->en_efop->efo_supported_filters(enp, list, length)) != 0)
+ if (buffer == NULL) {
+ rc = EINVAL;
goto fail1;
+ }
+
+ rc = enp->en_efop->efo_supported_filters(enp, buffer, buffer_length,
+ list_lengthp);
+ if (rc != 0)
+ goto fail2;
return (0);
+fail2:
+ EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
memset(spec, 0, sizeof (*spec));
spec->efs_priority = priority;
spec->efs_flags = EFX_FILTER_FLAG_RX | flags;
- spec->efs_rss_context = EFX_FILTER_SPEC_RSS_CONTEXT_DEFAULT;
+ spec->efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
spec->efs_dmaq_id = (uint16_t)erp->er_index;
}
return (0);
}
+ void
+efx_filter_spec_set_ether_type(
+ __inout efx_filter_spec_t *spec,
+ __in uint16_t ether_type)
+{
+ EFSYS_ASSERT3P(spec, !=, NULL);
+
+ spec->efs_ether_type = ether_type;
+ spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
+}
+
/*
* Specify matching otherwise-unmatched unicast in a filter specification
*/
{
EFSYS_ASSERT3P(spec, !=, NULL);
- spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
+ spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
return (0);
}
{
EFSYS_ASSERT3P(spec, !=, NULL);
- spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
- spec->efs_loc_mac[0] = 1;
+ spec->efs_match_flags |= EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
+ return (0);
+}
+
+
+__checkReturn efx_rc_t
+efx_filter_spec_set_encap_type(
+ __inout efx_filter_spec_t *spec,
+ __in efx_tunnel_protocol_t encap_type,
+ __in efx_filter_inner_frame_match_t inner_frame_match)
+{
+ uint32_t match_flags = 0;
+ uint8_t ip_proto;
+ efx_rc_t rc;
+
+ EFSYS_ASSERT3P(spec, !=, NULL);
+
+ switch (encap_type) {
+ case EFX_TUNNEL_PROTOCOL_VXLAN:
+ case EFX_TUNNEL_PROTOCOL_GENEVE:
+ ip_proto = EFX_IPPROTO_UDP;
+ break;
+ case EFX_TUNNEL_PROTOCOL_NVGRE:
+ ip_proto = EFX_IPPROTO_GRE;
+ break;
+ default:
+ EFSYS_ASSERT(0);
+ rc = EINVAL;
+ goto fail1;
+ }
+
+ switch (inner_frame_match) {
+ case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_MCAST_DST:
+ match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST;
+ break;
+ case EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_UCAST_DST:
+ match_flags |= EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST;
+ break;
+ case EFX_FILTER_INNER_FRAME_MATCH_OTHER:
+ /* This is for when specific inner frames are to be matched. */
+ break;
+ default:
+ EFSYS_ASSERT(0);
+ rc = EINVAL;
+ goto fail2;
+ }
+
+ spec->efs_encap_type = encap_type;
+ spec->efs_ip_proto = ip_proto;
+ spec->efs_match_flags |= (match_flags | EFX_FILTER_MATCH_IP_PROTO);
+
return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
}
+#if EFSYS_OPT_RX_SCALE
+ __checkReturn efx_rc_t
+efx_filter_spec_set_rss_context(
+ __inout efx_filter_spec_t *spec,
+ __in uint32_t rss_context)
+{
+ efx_rc_t rc;
+
+ EFSYS_ASSERT3P(spec, !=, NULL);
+
+ /* The filter must have been created with EFX_FILTER_FLAG_RX_RSS. */
+ if ((spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) == 0) {
+ rc = EINVAL;
+ goto fail1;
+ }
+
+ spec->efs_rss_context = rss_context;
+
+ return (0);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+#endif
#if EFSYS_OPT_SIENA
else
EFSYS_ASSERT3U(gen_spec->efs_flags, &, EFX_FILTER_FLAG_RX);
- /* Falconsiena only has one RSS context */
+ /* Siena only has one RSS context */
if ((gen_spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) &&
- gen_spec->efs_rss_context != 0) {
+ gen_spec->efs_rss_context != EFX_RSS_CONTEXT_DEFAULT) {
rc = EINVAL;
goto fail1;
}
return (rc);
}
-#define MAX_SUPPORTED 4
+#define SIENA_MAX_SUPPORTED_MATCHES 4
static __checkReturn efx_rc_t
siena_filter_supported_filters(
- __in efx_nic_t *enp,
- __out uint32_t *list,
- __out size_t *length)
+ __in efx_nic_t *enp,
+ __out_ecount(buffer_length) uint32_t *buffer,
+ __in size_t buffer_length,
+ __out size_t *list_lengthp)
{
- int index = 0;
- uint32_t rx_matches[MAX_SUPPORTED];
+ uint32_t index = 0;
+ uint32_t rx_matches[SIENA_MAX_SUPPORTED_MATCHES];
+ size_t list_length;
efx_rc_t rc;
- if (list == NULL) {
- rc = EINVAL;
- goto fail1;
- }
-
rx_matches[index++] =
EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
rx_matches[index++] = EFX_FILTER_MATCH_LOC_MAC;
}
- EFSYS_ASSERT3U(index, <=, MAX_SUPPORTED);
+ EFSYS_ASSERT3U(index, <=, SIENA_MAX_SUPPORTED_MATCHES);
+ list_length = index;
- *length = index;
- memcpy(list, rx_matches, *length);
+ *list_lengthp = list_length;
+
+ if (buffer_length < list_length) {
+ rc = ENOSPC;
+ goto fail1;
+ }
+
+ memcpy(buffer, rx_matches, list_length * sizeof (rx_matches[0]));
return (0);
fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}