Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F167518423
D59026.id184429.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D59026.id184429.diff
View Options
Index: share/man/man4/ice.4
===================================================================
--- share/man/man4/ice.4
+++ share/man/man4/ice.4
@@ -1143,11 +1143,20 @@
filter resources.
By default, this is set to 16.
.It max-mac-filters Pq uint16_t
-Specify maximum number of MAC address filters that the VF can use.
-Each allowed MAC address requires a hardware filter which are a finite
-resource; this is used to prevent a VF from starving other VFs or the PF of
-filter resources.
-The VF's default mac address does not count towards this limit.
+Specify the maximum number of unique MAC address filters that the VF can
+request.
+Repeated requests for the same address count once.
+Each allowed MAC address requires a hardware filter, which is a finite
+resource; this limit prevents a VF from starving other VFs or the PF of filter
+resources.
+A PF-assigned
+.Dq mac-addr
+does not count towards this limit.
+When
+.Dq mac-addr
+is omitted, a VF-chosen address, including an address randomly generated by
+.Xr iavf 4 ,
+counts as a unique filter.
By default, this is set to 64.
.El
.Pp
Index: sys/dev/ice/ice_iov.h
===================================================================
--- sys/dev/ice/ice_iov.h
+++ sys/dev/ice/ice_iov.h
@@ -75,6 +75,10 @@
VF_FLAG_RESET_FAILED = BIT(7),
};
+struct ice_vf_mac_filter {
+ u8 addr[ETHER_ADDR_LEN];
+};
+
/**
* @struct ice_vf
* @brief PF's VF software context
@@ -91,6 +95,7 @@
u16 mac_filter_limit;
u16 mac_filter_cnt;
+ struct ice_vf_mac_filter *mac_filters;
u16 vlan_limit;
u16 vlan_cnt;
#define ICE_VF_VLAN_MAP_LEN (EVL_VLID_MASK + 1)
Index: sys/dev/ice/ice_iov.c
===================================================================
--- sys/dev/ice/ice_iov.c
+++ sys/dev/ice/ice_iov.c
@@ -114,6 +114,7 @@
static int ice_vc_select_vlans(struct ice_vf *vf, u16 *vids, u16 count,
bool add, u16 *selected_count);
static enum virtchnl_status_code ice_iov_err_to_virt_err(int ice_err);
+static int ice_vf_mac_filter_index(struct ice_vf *vf, const uint8_t *addr);
static int ice_vf_validate_mac(struct ice_vf *vf, const uint8_t *addr);
#ifdef DRIVER_FAILPOINTS
@@ -530,6 +531,19 @@
vf->vlan_limit = nvlist_get_number(params, "max-vlan-allowed");
vf->mac_filter_limit = nvlist_get_number(params, "max-mac-filters");
+ if (vf->mac_filter_limit != 0) {
+ vf->mac_filters = mallocarray(vf->mac_filter_limit,
+ sizeof(*vf->mac_filters), M_ICE, M_NOWAIT | M_ZERO);
+ if (vf->mac_filters == NULL) {
+ device_printf(sc->dev,
+ "Unable to allocate VF-%d MAC filter memory\n",
+ vfnum);
+ error = ENOMEM;
+ goto release_imap;
+ }
+ }
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_mac_filter_memory, error,
+ free_mac_filters);
vf->vf_flags |= VF_FLAG_VLAN_CAP;
@@ -538,29 +552,33 @@
if (error) {
device_printf(sc->dev, "Unable to initialize VF %d VSI: %s\n",
vfnum, ice_err_str(error));
- goto release_imap;
+ goto free_mac_filters;
}
ICE_IOV_FAIL_POINT(sc, vfnum, add_after_vsi_init, error,
- release_imap);
+ free_mac_filters);
error = ice_iov_configure_mac_anti_spoof(sc, vf);
if (error != 0)
- goto release_imap;
+ goto free_mac_filters;
/* Add the broadcast address */
error = ice_add_vsi_mac_filter(vsi, broadcastaddr);
if (error) {
device_printf(sc->dev, "Unable to add broadcast filter VF %d VSI: %s\n",
vfnum, ice_err_str(error));
- goto release_imap;
+ goto free_mac_filters;
}
ICE_IOV_FAIL_POINT(sc, vfnum, add_after_broadcast_filter, error,
- release_imap);
+ free_mac_filters);
atomic_set_32(&vf->vf_flags, VF_FLAG_ENABLED);
ice_iov_ready_vf(sc, vf);
return (0);
+free_mac_filters:
+ free(vf->mac_filters, M_ICE);
+ vf->mac_filters = NULL;
+ vf->mac_filter_cnt = 0;
release_imap:
ice_resmgr_release_map(&sc->dev_imgr, vf->vf_imap,
vf->num_irq_vectors);
@@ -690,6 +708,9 @@
vf = &sc->vfs[i];
atomic_store_rel_32(&vf->vf_flags, 0);
vsi = vf->vsi;
+ free(vf->mac_filters, M_ICE);
+ vf->mac_filters = NULL;
+ vf->mac_filter_cnt = 0;
/* Free VF interrupt reservation */
if (vf->vf_imap) {
@@ -1267,6 +1288,25 @@
return (0);
}
+/**
+ * ice_vf_mac_filter_index - Find a VF-owned MAC filter
+ * @vf: VF tracking structure
+ * @addr: MAC address to find
+ *
+ * The administrator-assigned address does not consume the configurable VF
+ * filter quota and is therefore not stored in this array.
+ */
+static int
+ice_vf_mac_filter_index(struct ice_vf *vf, const uint8_t *addr)
+{
+
+ for (u16 i = 0; i < vf->mac_filter_cnt; i++) {
+ if (memcmp(vf->mac_filters[i].addr, addr, ETHER_ADDR_LEN) == 0)
+ return (i);
+ }
+ return (-1);
+}
+
/**
* ice_vc_add_eth_addr_msg - Handle VIRTCHNL_OP_ADD_ETH_ADDR msg from VF
* @sc: device private structure
@@ -1282,38 +1322,50 @@
enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS;
struct virtchnl_ether_addr_list *addr_list;
struct ice_hw *hw = &sc->hw;
- u16 added_addr_cnt = 0;
+ u16 new_filters;
int error = 0;
addr_list = (struct virtchnl_ether_addr_list *)msg_buf;
- if (addr_list->num_elements >
- (vf->mac_filter_limit - vf->mac_filter_cnt)) {
+ /* Validate the entire batch and charge only unique, absent filters. */
+ new_filters = 0;
+ for (int i = 0; i < addr_list->num_elements; i++) {
+ u8 *addr = addr_list->list[i].addr;
+ int j;
+
+ error = ice_vf_validate_mac(vf, addr);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "%s: VF-%d: invalid or unauthorized MAC for VSI %d\n",
+ __func__, vf->vf_num, vf->vsi->idx);
+ v_status = VIRTCHNL_STATUS_ERR_PARAM;
+ goto done;
+ }
+ for (j = 0; j < i; j++) {
+ if (memcmp(addr_list->list[j].addr, addr,
+ ETHER_ADDR_LEN) == 0)
+ break;
+ }
+ if (j != i || memcmp(addr, vf->mac, ETHER_ADDR_LEN) == 0 ||
+ ice_vf_mac_filter_index(vf, addr) >= 0)
+ continue;
+ new_filters++;
+ }
+ if ((u32)vf->mac_filter_cnt + new_filters > vf->mac_filter_limit) {
v_status = VIRTCHNL_STATUS_ERR_NO_MEMORY;
goto done;
}
for (int i = 0; i < addr_list->num_elements; i++) {
u8 *addr = addr_list->list[i].addr;
+ bool assigned;
/* The type flag is currently ignored; every MAC address is
* treated as the LEGACY type
*/
-
- error = ice_vf_validate_mac(vf, addr);
- if (error == EPERM) {
- device_printf(sc->dev,
- "%s: VF-%d: Not permitted to add MAC addr for VSI %d\n",
- __func__, vf->vf_num, vf->vsi->idx);
- v_status = VIRTCHNL_STATUS_ERR_PARAM;
- continue;
- } else if (error) {
- device_printf(sc->dev,
- "%s: VF-%d: Did not add invalid MAC addr for VSI %d\n",
- __func__, vf->vf_num, vf->vsi->idx);
- v_status = VIRTCHNL_STATUS_ERR_PARAM;
+ assigned = memcmp(addr, vf->mac, ETHER_ADDR_LEN) == 0;
+ if (!assigned && ice_vf_mac_filter_index(vf, addr) >= 0)
continue;
- }
error = ice_add_vsi_mac_filter(vf->vsi, addr);
if (error) {
@@ -1323,13 +1375,14 @@
v_status = VIRTCHNL_STATUS_ERR_PARAM;
continue;
}
- /* Don't count VF's MAC against its MAC filter limit */
- if (memcmp(addr, vf->mac, ETHER_ADDR_LEN))
- added_addr_cnt++;
+ if (!assigned) {
+ MPASS(vf->mac_filter_cnt < vf->mac_filter_limit);
+ memcpy(vf->mac_filters[vf->mac_filter_cnt].addr, addr,
+ ETHER_ADDR_LEN);
+ vf->mac_filter_cnt++;
+ }
}
- vf->mac_filter_cnt += added_addr_cnt;
-
done:
ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_ADD_ETH_ADDR,
v_status, NULL, 0, NULL);
@@ -1350,13 +1403,29 @@
enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS;
struct virtchnl_ether_addr_list *addr_list;
struct ice_hw *hw = &sc->hw;
- u16 deleted_addr_cnt = 0;
int error = 0;
addr_list = (struct virtchnl_ether_addr_list *)msg_buf;
for (int i = 0; i < addr_list->num_elements; i++) {
- error = ice_remove_vsi_mac_filter(vf->vsi, addr_list->list[i].addr);
+ u8 *addr = addr_list->list[i].addr;
+ bool assigned;
+ int index;
+
+ error = ice_vf_validate_mac(vf, addr);
+ if (error != 0) {
+ v_status = VIRTCHNL_STATUS_ERR_PARAM;
+ continue;
+ }
+ assigned = memcmp(addr, vf->mac, ETHER_ADDR_LEN) == 0;
+ if (assigned &&
+ (vf->vf_flags & VF_FLAG_SET_MAC_CAP) == 0)
+ continue;
+ index = assigned ? -1 : ice_vf_mac_filter_index(vf, addr);
+ if (!assigned && index < 0)
+ continue;
+
+ error = ice_remove_vsi_mac_filter(vf->vsi, addr);
if (error) {
device_printf(sc->dev,
"%s: VF-%d: Error removing MAC addr for VSI %d\n",
@@ -1364,16 +1433,17 @@
v_status = VIRTCHNL_STATUS_ERR_PARAM;
continue;
}
- /* Don't count VF's MAC against its MAC filter limit */
- if (memcmp(addr_list->list[i].addr, vf->mac, ETHER_ADDR_LEN))
- deleted_addr_cnt++;
+ if (!assigned) {
+ if (index + 1 < vf->mac_filter_cnt) {
+ memmove(&vf->mac_filters[index],
+ &vf->mac_filters[index + 1],
+ (vf->mac_filter_cnt - index - 1) *
+ sizeof(*vf->mac_filters));
+ }
+ vf->mac_filter_cnt--;
+ }
}
- if (deleted_addr_cnt >= vf->mac_filter_cnt)
- vf->mac_filter_cnt = 0;
- else
- vf->mac_filter_cnt -= deleted_addr_cnt;
-
ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_DEL_ETH_ADDR,
v_status, NULL, 0, NULL);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Aug 23, 10:40 AM (4 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37126766
Default Alt Text
D59026.id184429.diff (8 KB)
Attached To
Mode
D59026: ice: Make VF MAC filter requests idempotent
Attached
Detach File
Event Timeline
Log In to Comment