net/sfc/base: reject automatic filter creation by users
[dpdk.git] / drivers / net / sfc / base / efx_filter.c
index 2e6628b..36332a2 100644 (file)
@@ -56,7 +56,7 @@ static const efx_filter_ops_t __efx_filter_siena_ops = {
 };
 #endif /* EFSYS_OPT_SIENA */
 
-#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
+#if EFX_OPTS_EF10()
 static const efx_filter_ops_t  __efx_filter_ef10_ops = {
        ef10_filter_init,               /* efo_init */
        ef10_filter_fini,               /* efo_fini */
@@ -66,7 +66,7 @@ static const efx_filter_ops_t __efx_filter_ef10_ops = {
        ef10_filter_supported_filters,  /* efo_supported_filters */
        ef10_filter_reconfigure,        /* efo_reconfigure */
 };
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
+#endif /* EFX_OPTS_EF10() */
 
        __checkReturn   efx_rc_t
 efx_filter_insert(
@@ -74,12 +74,40 @@ efx_filter_insert(
        __inout         efx_filter_spec_t *spec)
 {
        const efx_filter_ops_t *efop = enp->en_efop;
+       efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+       efx_rc_t rc;
 
        EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_FILTER);
        EFSYS_ASSERT3P(spec, !=, NULL);
        EFSYS_ASSERT3U(spec->efs_flags, &, EFX_FILTER_FLAG_RX);
 
+       if ((spec->efs_flags & EFX_FILTER_FLAG_ACTION_MARK) &&
+           !encp->enc_filter_action_mark_supported) {
+               rc = ENOTSUP;
+               goto fail1;
+       }
+
+       if ((spec->efs_flags & EFX_FILTER_FLAG_ACTION_FLAG) &&
+           !encp->enc_filter_action_flag_supported) {
+               rc = ENOTSUP;
+               goto fail2;
+       }
+
+       if (spec->efs_priority == EFX_FILTER_PRI_AUTO) {
+               rc = EINVAL;
+               goto fail3;
+       }
+
        return (efop->efo_add(enp, spec, B_FALSE));
+
+fail3:
+       EFSYS_PROBE(fail3);
+fail2:
+       EFSYS_PROBE(fail2);
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
 }
 
        __checkReturn   efx_rc_t
@@ -293,7 +321,7 @@ efx_filter_spec_init_tx(
        EFSYS_ASSERT3P(etp, !=, NULL);
 
        memset(spec, 0, sizeof (*spec));
-       spec->efs_priority = EFX_FILTER_PRI_REQUIRED;
+       spec->efs_priority = EFX_FILTER_PRI_MANUAL;
        spec->efs_flags = EFX_FILTER_FLAG_TX;
        spec->efs_dmaq_id = (uint16_t)etp->et_index;
 }
@@ -418,7 +446,7 @@ efx_filter_spec_set_encap_type(
        __in            efx_tunnel_protocol_t encap_type,
        __in            efx_filter_inner_frame_match_t inner_frame_match)
 {
-       uint32_t match_flags = 0;
+       uint32_t match_flags = EFX_FILTER_MATCH_ENCAP_TYPE;
        uint8_t ip_proto;
        efx_rc_t rc;
 
@@ -469,27 +497,42 @@ fail1:
 }
 
 /*
- * Specify inner and outer Ethernet address and VXLAN ID in filter
+ * Specify inner and outer Ethernet address and VNI or VSID in tunnel filter
  * specification.
  */
-       __checkReturn   efx_rc_t
-efx_filter_spec_set_vxlan_full(
-       __inout         efx_filter_spec_t *spec,
-       __in            const uint8_t *vxlan_id,
+static __checkReturn   efx_rc_t
+efx_filter_spec_set_tunnel(
+       __inout efx_filter_spec_t *spec,
+       __in            efx_tunnel_protocol_t encap_type,
+       __in            const uint8_t *vni_or_vsid,
        __in            const uint8_t *inner_addr,
        __in            const uint8_t *outer_addr)
 {
+       efx_rc_t rc;
+
        EFSYS_ASSERT3P(spec, !=, NULL);
-       EFSYS_ASSERT3P(vxlan_id, !=, NULL);
+       EFSYS_ASSERT3P(vni_or_vsid, !=, NULL);
        EFSYS_ASSERT3P(inner_addr, !=, NULL);
        EFSYS_ASSERT3P(outer_addr, !=, NULL);
 
-       if ((inner_addr == NULL) && (outer_addr == NULL))
-               return (EINVAL);
+       switch (encap_type) {
+       case EFX_TUNNEL_PROTOCOL_VXLAN:
+       case EFX_TUNNEL_PROTOCOL_GENEVE:
+       case EFX_TUNNEL_PROTOCOL_NVGRE:
+               break;
+       default:
+               rc = EINVAL;
+               goto fail1;
+       }
 
-       if (vxlan_id != NULL) {
+       if ((inner_addr == NULL) && (outer_addr == NULL)) {
+               rc = EINVAL;
+               goto fail2;
+       }
+
+       if (vni_or_vsid != NULL) {
                spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID;
-               memcpy(spec->efs_vni_or_vsid, vxlan_id, EFX_VNI_OR_VSID_LEN);
+               memcpy(spec->efs_vni_or_vsid, vni_or_vsid, EFX_VNI_OR_VSID_LEN);
        }
        if (outer_addr != NULL) {
                spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
@@ -499,9 +542,63 @@ efx_filter_spec_set_vxlan_full(
                spec->efs_match_flags |= EFX_FILTER_MATCH_IFRM_LOC_MAC;
                memcpy(spec->efs_ifrm_loc_mac, inner_addr, EFX_MAC_ADDR_LEN);
        }
-       spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
+
+       spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
+       spec->efs_encap_type = encap_type;
 
        return (0);
+
+fail2:
+       EFSYS_PROBE(fail2);
+fail1:
+       EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+       return (rc);
+}
+
+/*
+ * Specify inner and outer Ethernet address and VNI in VXLAN filter
+ * specification.
+ */
+__checkReturn          efx_rc_t
+efx_filter_spec_set_vxlan(
+       __inout         efx_filter_spec_t *spec,
+       __in            const uint8_t *vni,
+       __in            const uint8_t *inner_addr,
+       __in            const uint8_t *outer_addr)
+{
+       return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_VXLAN,
+           vni, inner_addr, outer_addr);
+}
+
+/*
+ * Specify inner and outer Ethernet address and VNI in Geneve filter
+ * specification.
+ */
+__checkReturn          efx_rc_t
+efx_filter_spec_set_geneve(
+       __inout         efx_filter_spec_t *spec,
+       __in            const uint8_t *vni,
+       __in            const uint8_t *inner_addr,
+       __in            const uint8_t *outer_addr)
+{
+       return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_GENEVE,
+           vni, inner_addr, outer_addr);
+}
+
+/*
+ * Specify inner and outer Ethernet address and vsid in NVGRE filter
+ * specification.
+ */
+__checkReturn          efx_rc_t
+efx_filter_spec_set_nvgre(
+       __inout         efx_filter_spec_t *spec,
+       __in            const uint8_t *vsid,
+       __in            const uint8_t *inner_addr,
+       __in            const uint8_t *outer_addr)
+{
+       return efx_filter_spec_set_tunnel(spec, EFX_TUNNEL_PROTOCOL_NVGRE,
+           vsid, inner_addr, outer_addr);
 }
 
 #if EFSYS_OPT_RX_SCALE