@@ -4437,6 +4437,34 @@ extern __checkReturn efx_rc_t
efx_mae_action_set_populate_vlan_pop(
__in efx_mae_actions_t *spec);
+/*
+ * This always amends the outermost header. This way, for a tunnel
+ * packet, if action DECAP is not requested, this will affect the
+ * outer header; otherwise, the inner header will be updated.
+ *
+ * Use efx_mae_action_set_fill_in_dst_mac_id() to set ID of
+ * the allocated MAC address entry in the specification
+ * prior to action set allocation.
+ */
+LIBEFX_API
+extern __checkReturn efx_rc_t
+efx_mae_action_set_populate_set_dst_mac(
+ __in efx_mae_actions_t *spec);
+
+/*
+ * This always amends the outermost header. This way, for a tunnel
+ * packet, if action DECAP is not requested, this will affect the
+ * outer header; otherwise, the inner header will be updated.
+ *
+ * Use efx_mae_action_set_fill_in_src_mac_id() to set ID of
+ * the allocated MAC address entry in the specification
+ * prior to action set allocation.
+ */
+LIBEFX_API
+extern __checkReturn efx_rc_t
+efx_mae_action_set_populate_set_src_mac(
+ __in efx_mae_actions_t *spec);
+
/*
* This always amends the outermost header. This way, for a tunnel
* packet, if action DECAP is not requested, this will affect the
@@ -4570,6 +4598,38 @@ efx_mae_match_spec_outer_rule_id_set(
__in efx_mae_match_spec_t *spec,
__in const efx_mae_rule_id_t *or_idp);
+/* MAC address entry ID */
+typedef struct efx_mae_mac_id_s {
+ uint32_t id;
+} efx_mae_mac_id_t;
+
+LIBEFX_API
+extern __checkReturn efx_rc_t
+efx_mae_mac_addr_alloc(
+ __in efx_nic_t *enp,
+ __in uint8_t addr_bytes[EFX_MAC_ADDR_LEN],
+ __out efx_mae_mac_id_t *mac_idp);
+
+LIBEFX_API
+extern __checkReturn efx_rc_t
+efx_mae_mac_addr_free(
+ __in efx_nic_t *enp,
+ __in const efx_mae_mac_id_t *mac_idp);
+
+/* See description before efx_mae_action_set_populate_set_dst_mac(). */
+LIBEFX_API
+extern __checkReturn efx_rc_t
+efx_mae_action_set_fill_in_dst_mac_id(
+ __in efx_mae_actions_t *spec,
+ __in const efx_mae_mac_id_t *mac_idp);
+
+/* See description before efx_mae_action_set_populate_set_src_mac(). */
+LIBEFX_API
+extern __checkReturn efx_rc_t
+efx_mae_action_set_fill_in_src_mac_id(
+ __in efx_mae_actions_t *spec,
+ __in const efx_mae_mac_id_t *mac_idp);
+
/* Encap. header ID */
typedef struct efx_mae_eh_id_s {
uint32_t id;
@@ -1740,6 +1740,8 @@ typedef enum efx_mae_action_e {
/* These actions are strictly ordered. */
EFX_MAE_ACTION_DECAP,
EFX_MAE_ACTION_VLAN_POP,
+ EFX_MAE_ACTION_SET_DST_MAC,
+ EFX_MAE_ACTION_SET_SRC_MAC,
EFX_MAE_ACTION_DECR_IP_TTL,
EFX_MAE_ACTION_VLAN_PUSH,
EFX_MAE_ACTION_COUNT,
@@ -1772,6 +1774,8 @@ typedef struct efx_mae_action_vlan_push_s {
} efx_mae_action_vlan_push_t;
typedef struct efx_mae_actions_rsrc_s {
+ efx_mae_mac_id_t emar_dst_mac_id;
+ efx_mae_mac_id_t emar_src_mac_id;
efx_mae_eh_id_t emar_eh_id;
efx_counter_t emar_counter_id;
} efx_mae_actions_rsrc_t;
@@ -1386,6 +1386,8 @@ efx_mae_action_set_spec_init(
goto fail1;
}
+ spec->ema_rsrc.emar_dst_mac_id.id = EFX_MAE_RSRC_ID_INVALID;
+ spec->ema_rsrc.emar_src_mac_id.id = EFX_MAE_RSRC_ID_INVALID;
spec->ema_rsrc.emar_eh_id.id = EFX_MAE_RSRC_ID_INVALID;
spec->ema_rsrc.emar_counter_id.id = EFX_MAE_RSRC_ID_INVALID;
@@ -1633,6 +1635,12 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
[EFX_MAE_ACTION_VLAN_POP] = {
.emad_add = efx_mae_action_set_add_vlan_pop
},
+ [EFX_MAE_ACTION_SET_DST_MAC] = {
+ .emad_add = efx_mae_action_set_no_op
+ },
+ [EFX_MAE_ACTION_SET_SRC_MAC] = {
+ .emad_add = efx_mae_action_set_no_op
+ },
[EFX_MAE_ACTION_DECR_IP_TTL] = {
.emad_add = efx_mae_action_set_no_op
},
@@ -1659,6 +1667,8 @@ static const efx_mae_action_desc_t efx_mae_actions[EFX_MAE_NACTIONS] = {
static const uint32_t efx_mae_action_ordered_map =
(1U << EFX_MAE_ACTION_DECAP) |
(1U << EFX_MAE_ACTION_VLAN_POP) |
+ (1U << EFX_MAE_ACTION_SET_DST_MAC) |
+ (1U << EFX_MAE_ACTION_SET_SRC_MAC) |
(1U << EFX_MAE_ACTION_DECR_IP_TTL) |
(1U << EFX_MAE_ACTION_VLAN_PUSH) |
/*
@@ -1778,6 +1788,44 @@ efx_mae_action_set_populate_vlan_pop(
EFX_MAE_ACTION_VLAN_POP, 0, NULL));
}
+ __checkReturn efx_rc_t
+efx_mae_action_set_populate_set_dst_mac(
+ __in efx_mae_actions_t *spec)
+{
+ efx_rc_t rc;
+
+ if (spec->ema_v2_is_supported == B_FALSE) {
+ rc = ENOTSUP;
+ goto fail1;
+ }
+
+ return (efx_mae_action_set_spec_populate(spec,
+ EFX_MAE_ACTION_SET_DST_MAC, 0, NULL));
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ return (rc);
+}
+
+ __checkReturn efx_rc_t
+efx_mae_action_set_populate_set_src_mac(
+ __in efx_mae_actions_t *spec)
+{
+ efx_rc_t rc;
+
+ if (spec->ema_v2_is_supported == B_FALSE) {
+ rc = ENOTSUP;
+ goto fail1;
+ }
+
+ return (efx_mae_action_set_spec_populate(spec,
+ EFX_MAE_ACTION_SET_SRC_MAC, 0, NULL));
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ return (rc);
+}
+
__checkReturn efx_rc_t
efx_mae_action_set_populate_decr_ip_ttl(
__in efx_mae_actions_t *spec)
@@ -2317,6 +2365,224 @@ efx_mae_match_spec_outer_rule_id_set(
return (0);
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ return (rc);
+}
+
+ __checkReturn efx_rc_t
+efx_mae_mac_addr_alloc(
+ __in efx_nic_t *enp,
+ __in uint8_t addr_bytes[EFX_MAC_ADDR_LEN],
+ __out efx_mae_mac_id_t *mac_idp)
+{
+ const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+ efx_mcdi_req_t req;
+ EFX_MCDI_DECLARE_BUF(payload,
+ MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN,
+ MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN);
+ efx_mae_mac_id_t mac_id;
+ efx_rc_t rc;
+
+ EFX_STATIC_ASSERT(sizeof (mac_idp->id) ==
+ MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_LEN);
+
+ EFX_STATIC_ASSERT(EFX_MAE_RSRC_ID_INVALID ==
+ MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
+
+ if (encp->enc_mae_supported == B_FALSE) {
+ rc = ENOTSUP;
+ goto fail1;
+ }
+
+ if (encp->enc_mae_aset_v2_supported == B_FALSE) {
+ rc = ENOTSUP;
+ goto fail2;
+ }
+
+ req.emr_cmd = MC_CMD_MAE_MAC_ADDR_ALLOC;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN;
+
+ memcpy(payload + MC_CMD_MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR_OFST,
+ addr_bytes, EFX_MAC_ADDR_LEN);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail3;
+ }
+
+ if (req.emr_out_length_used < MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN) {
+ rc = EMSGSIZE;
+ goto fail4;
+ }
+
+ mac_id.id = MCDI_OUT_DWORD(req, MAE_MAC_ADDR_ALLOC_OUT_MAC_ID);
+ if (mac_id.id == EFX_MAE_RSRC_ID_INVALID) {
+ rc = ENOENT;
+ goto fail5;
+ }
+
+ mac_idp->id = mac_id.id;
+
+ return (0);
+
+fail5:
+ EFSYS_PROBE(fail5);
+fail4:
+ EFSYS_PROBE(fail4);
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ return (rc);
+}
+
+ __checkReturn efx_rc_t
+efx_mae_mac_addr_free(
+ __in efx_nic_t *enp,
+ __in const efx_mae_mac_id_t *mac_idp)
+{
+ const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
+ efx_mcdi_req_t req;
+ EFX_MCDI_DECLARE_BUF(payload,
+ MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(1),
+ MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1));
+ efx_rc_t rc;
+
+ if (encp->enc_mae_supported == B_FALSE) {
+ rc = ENOTSUP;
+ goto fail1;
+ }
+
+ if (encp->enc_mae_aset_v2_supported == B_FALSE) {
+ rc = ENOTSUP;
+ goto fail2;
+ }
+
+ req.emr_cmd = MC_CMD_MAE_MAC_ADDR_FREE;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(1);
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1);
+
+ MCDI_IN_SET_DWORD(req, MAE_MAC_ADDR_FREE_IN_MAC_ID, mac_idp->id);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail3;
+ }
+
+ if (req.emr_out_length_used < MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1)) {
+ rc = EMSGSIZE;
+ goto fail4;
+ }
+
+ if (MCDI_OUT_DWORD(req, MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID) !=
+ mac_idp->id) {
+ /* Firmware failed to remove the MAC address entry. */
+ rc = EAGAIN;
+ goto fail5;
+ }
+
+ return (0);
+
+fail5:
+ EFSYS_PROBE(fail5);
+fail4:
+ EFSYS_PROBE(fail4);
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ return (rc);
+}
+
+ __checkReturn efx_rc_t
+efx_mae_action_set_fill_in_dst_mac_id(
+ __in efx_mae_actions_t *spec,
+ __in const efx_mae_mac_id_t *mac_idp)
+{
+ efx_rc_t rc;
+
+ if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_DST_MAC)) == 0) {
+ /*
+ * The caller has not intended to have this action originally,
+ * hence, they cannot indicate the MAC address entry ID.
+ */
+ rc = EINVAL;
+ goto fail1;
+ }
+
+ if (spec->ema_rsrc.emar_dst_mac_id.id != EFX_MAE_RSRC_ID_INVALID) {
+ /* An attempt to indicate the MAC address entry ID twice. */
+ rc = EINVAL;
+ goto fail2;
+ }
+
+ if (mac_idp->id == EFX_MAE_RSRC_ID_INVALID) {
+ rc = EINVAL;
+ goto fail3;
+ }
+
+ spec->ema_rsrc.emar_dst_mac_id.id = mac_idp->id;
+
+ return (0);
+
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ return (rc);
+}
+
+ __checkReturn efx_rc_t
+efx_mae_action_set_fill_in_src_mac_id(
+ __in efx_mae_actions_t *spec,
+ __in const efx_mae_mac_id_t *mac_idp)
+{
+ efx_rc_t rc;
+
+ if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_SRC_MAC)) == 0) {
+ /*
+ * The caller has not intended to have this action originally,
+ * hence, they cannot indicate the MAC address entry ID.
+ */
+ rc = EINVAL;
+ goto fail1;
+ }
+
+ if (spec->ema_rsrc.emar_src_mac_id.id != EFX_MAE_RSRC_ID_INVALID) {
+ /* An attempt to indicate the MAC address entry ID twice. */
+ rc = EINVAL;
+ goto fail2;
+ }
+
+ if (mac_idp->id == EFX_MAE_RSRC_ID_INVALID) {
+ rc = EINVAL;
+ goto fail3;
+ }
+
+ spec->ema_rsrc.emar_src_mac_id.id = mac_idp->id;
+
+ return (0);
+
fail3:
EFSYS_PROBE(fail3);
fail2:
@@ -2538,16 +2804,28 @@ efx_mae_action_set_alloc(
goto fail1;
}
+ if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_DST_MAC)) != 0 &&
+ spec->ema_rsrc.emar_dst_mac_id.id == EFX_MAE_RSRC_ID_INVALID) {
+ rc = EINVAL;
+ goto fail2;
+ }
+
+ if ((spec->ema_actions & (1U << EFX_MAE_ACTION_SET_SRC_MAC)) != 0 &&
+ spec->ema_rsrc.emar_src_mac_id.id == EFX_MAE_RSRC_ID_INVALID) {
+ rc = EINVAL;
+ goto fail3;
+ }
+
if ((spec->ema_actions & (1U << EFX_MAE_ACTION_ENCAP)) != 0 &&
spec->ema_rsrc.emar_eh_id.id == EFX_MAE_RSRC_ID_INVALID) {
rc = EINVAL;
- goto fail2;
+ goto fail4;
}
if (spec->ema_n_count_actions == 1 &&
spec->ema_rsrc.emar_counter_id.id == EFX_MAE_RSRC_ID_INVALID) {
rc = EINVAL;
- goto fail3;
+ goto fail5;
}
req.emr_cmd = MC_CMD_MAE_ACTION_SET_ALLOC;
@@ -2572,6 +2850,12 @@ efx_mae_action_set_alloc(
MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
MAE_ACTION_SET_ALLOC_IN_VLAN_POP, spec->ema_n_vlan_tags_to_pop);
+ MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID,
+ spec->ema_rsrc.emar_dst_mac_id.id);
+
+ MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID,
+ spec->ema_rsrc.emar_src_mac_id.id);
+
if ((spec->ema_actions & (1U << EFX_MAE_ACTION_DECR_IP_TTL)) != 0) {
MCDI_IN_SET_DWORD_FIELD(req, MAE_ACTION_SET_ALLOC_IN_FLAGS,
MAE_ACTION_SET_ALLOC_IN_DO_DECR_IP_TTL, 1);
@@ -2623,33 +2907,32 @@ efx_mae_action_set_alloc(
MCDI_IN_SET_DWORD(req,
MAE_ACTION_SET_ALLOC_IN_DELIVER, spec->ema_deliver_mport.sel);
- MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID,
- MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
- MCDI_IN_SET_DWORD(req, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID,
- MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL);
-
efx_mcdi_execute(enp, &req);
if (req.emr_rc != 0) {
rc = req.emr_rc;
- goto fail4;
+ goto fail6;
}
if (req.emr_out_length_used < MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN) {
rc = EMSGSIZE;
- goto fail5;
+ goto fail7;
}
aset_id.id = MCDI_OUT_DWORD(req, MAE_ACTION_SET_ALLOC_OUT_AS_ID);
if (aset_id.id == EFX_MAE_RSRC_ID_INVALID) {
rc = ENOENT;
- goto fail6;
+ goto fail8;
}
aset_idp->id = aset_id.id;
return (0);
+fail8:
+ EFSYS_PROBE(fail8);
+fail7:
+ EFSYS_PROBE(fail7);
fail6:
EFSYS_PROBE(fail6);
fail5:
@@ -90,7 +90,9 @@ INTERNAL {
efx_mae_action_rule_remove;
efx_mae_action_set_alloc;
efx_mae_action_set_fill_in_counter_id;
+ efx_mae_action_set_fill_in_dst_mac_id;
efx_mae_action_set_fill_in_eh_id;
+ efx_mae_action_set_fill_in_src_mac_id;
efx_mae_action_set_free;
efx_mae_action_set_get_nb_count;
efx_mae_action_set_populate_count;
@@ -101,6 +103,8 @@ INTERNAL {
efx_mae_action_set_populate_encap;
efx_mae_action_set_populate_flag;
efx_mae_action_set_populate_mark;
+ efx_mae_action_set_populate_set_dst_mac;
+ efx_mae_action_set_populate_set_src_mac;
efx_mae_action_set_populate_vlan_pop;
efx_mae_action_set_populate_vlan_push;
efx_mae_action_set_spec_fini;
@@ -116,6 +120,8 @@ INTERNAL {
efx_mae_fini;
efx_mae_get_limits;
efx_mae_init;
+ efx_mae_mac_addr_alloc;
+ efx_mae_mac_addr_free;
efx_mae_match_spec_bit_set;
efx_mae_match_spec_field_set;
efx_mae_match_spec_fini;