/*-
+ * BSD LICENSE
+ *
* Copyright (c) 2017 Solarflare Communications Inc.
* All rights reserved.
*
*
* @param item[in]
* Item specification. Only source and destination addresses and
- * Ethernet type fields are supported. If the mask is NULL, default
- * mask will be used. Ranging is not supported.
+ * Ethernet type fields are supported. In addition to full and
+ * empty masks of destination address, individual/group mask is
+ * also supported. If the mask is NULL, default mask will be used.
+ * Ranging is not supported.
* @param efx_spec[in, out]
* EFX filter specification to update.
* @param[out] error
.src.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
.type = 0xffff,
};
+ const uint8_t ig_mask[EFX_MAC_ADDR_LEN] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
rc = sfc_flow_parse_init(item,
(const void **)&spec,
efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
rte_memcpy(efx_spec->efs_loc_mac, spec->dst.addr_bytes,
EFX_MAC_ADDR_LEN);
+ } else if (memcmp(mask->dst.addr_bytes, ig_mask,
+ EFX_MAC_ADDR_LEN) == 0) {
+ if (is_unicast_ether_addr(&spec->dst))
+ efx_spec->efs_match_flags |=
+ EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
+ else
+ efx_spec->efs_match_flags |=
+ EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
} else if (!is_zero_ether_addr(&mask->dst)) {
goto fail_bad_mask;
}
return -rte_errno;
}
- for (; pattern != NULL &&
- pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
+ for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
item = sfc_flow_get_item(pattern->type);
if (item == NULL) {
rte_flow_error_set(error, ENOTSUP,
prev_layer = item->layer;
}
- if (pattern == NULL) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ITEM, NULL,
- "NULL item");
- return -rte_errno;
- }
-
return 0;
}
return -ret;
}
+static int
+sfc_flow_isolate(struct rte_eth_dev *dev, int enable,
+ struct rte_flow_error *error)
+{
+ struct sfc_adapter *sa = dev->data->dev_private;
+ struct sfc_port *port = &sa->port;
+ int ret = 0;
+
+ sfc_adapter_lock(sa);
+ if (sa->state != SFC_ADAPTER_INITIALIZED) {
+ rte_flow_error_set(error, EBUSY,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "please close the port first");
+ ret = -rte_errno;
+ } else {
+ port->isolated = (enable) ? B_TRUE : B_FALSE;
+ }
+ sfc_adapter_unlock(sa);
+
+ return ret;
+}
+
const struct rte_flow_ops sfc_flow_ops = {
.validate = sfc_flow_validate,
.create = sfc_flow_create,
.destroy = sfc_flow_destroy,
.flush = sfc_flow_flush,
.query = NULL,
+ .isolate = sfc_flow_isolate,
};
void