aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/ice/ice_switch.c
diff options
context:
space:
mode:
authorAkeem G Abodunrin <akeem.g.abodunrin@intel.com>2019-02-26 19:35:14 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2019-03-22 11:19:17 -0400
commit5eda8afd6bcc89d4e4aa5d56b5f54276f63158ae (patch)
tree44a9e13481cd5aa025b5f576a09f93fa943bb9fa /drivers/net/ethernet/intel/ice/ice_switch.c
parente1ca65a3cceacc94dd9cde388016422ca2e15a54 (diff)
ice: Add support for PF/VF promiscuous mode
Implement support for VF promiscuous mode, MAC/VLAN/MAC_VLAN and PF multicast MAC/VLAN/MAC_VLAN promiscuous mode. Signed-off-by: Akeem G Abodunrin <akeem.g.abodunrin@intel.com> Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_switch.c')
-rw-r--r--drivers/net/ethernet/intel/ice/ice_switch.c291
1 files changed, 289 insertions, 2 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
index ed87361f6112..64e9e0cb61ce 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -2190,6 +2190,291 @@ ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
2190} 2190}
2191 2191
2192/** 2192/**
2193 * ice_determine_promisc_mask
2194 * @fi: filter info to parse
2195 *
2196 * Helper function to determine which ICE_PROMISC_ mask corresponds
2197 * to given filter into.
2198 */
2199static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
2200{
2201 u16 vid = fi->l_data.mac_vlan.vlan_id;
2202 u8 *macaddr = fi->l_data.mac.mac_addr;
2203 bool is_tx_fltr = false;
2204 u8 promisc_mask = 0;
2205
2206 if (fi->flag == ICE_FLTR_TX)
2207 is_tx_fltr = true;
2208
2209 if (is_broadcast_ether_addr(macaddr))
2210 promisc_mask |= is_tx_fltr ?
2211 ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
2212 else if (is_multicast_ether_addr(macaddr))
2213 promisc_mask |= is_tx_fltr ?
2214 ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
2215 else if (is_unicast_ether_addr(macaddr))
2216 promisc_mask |= is_tx_fltr ?
2217 ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
2218 if (vid)
2219 promisc_mask |= is_tx_fltr ?
2220 ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
2221
2222 return promisc_mask;
2223}
2224
2225/**
2226 * ice_remove_promisc - Remove promisc based filter rules
2227 * @hw: pointer to the hardware structure
2228 * @recp_id: recipe id for which the rule needs to removed
2229 * @v_list: list of promisc entries
2230 */
2231static enum ice_status
2232ice_remove_promisc(struct ice_hw *hw, u8 recp_id,
2233 struct list_head *v_list)
2234{
2235 struct ice_fltr_list_entry *v_list_itr, *tmp;
2236
2237 list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
2238 v_list_itr->status =
2239 ice_remove_rule_internal(hw, recp_id, v_list_itr);
2240 if (v_list_itr->status)
2241 return v_list_itr->status;
2242 }
2243 return 0;
2244}
2245
2246/**
2247 * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
2248 * @hw: pointer to the hardware structure
2249 * @vsi_handle: VSI handle to clear mode
2250 * @promisc_mask: mask of promiscuous config bits to clear
2251 * @vid: VLAN ID to clear VLAN promiscuous
2252 */
2253enum ice_status
2254ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
2255 u16 vid)
2256{
2257 struct ice_switch_info *sw = hw->switch_info;
2258 struct ice_fltr_list_entry *fm_entry, *tmp;
2259 struct list_head remove_list_head;
2260 struct ice_fltr_mgmt_list_entry *itr;
2261 struct list_head *rule_head;
2262 struct mutex *rule_lock; /* Lock to protect filter rule list */
2263 enum ice_status status = 0;
2264 u8 recipe_id;
2265
2266 if (!ice_is_vsi_valid(hw, vsi_handle))
2267 return ICE_ERR_PARAM;
2268
2269 if (vid)
2270 recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
2271 else
2272 recipe_id = ICE_SW_LKUP_PROMISC;
2273
2274 rule_head = &sw->recp_list[recipe_id].filt_rules;
2275 rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
2276
2277 INIT_LIST_HEAD(&remove_list_head);
2278
2279 mutex_lock(rule_lock);
2280 list_for_each_entry(itr, rule_head, list_entry) {
2281 u8 fltr_promisc_mask = 0;
2282
2283 if (!ice_vsi_uses_fltr(itr, vsi_handle))
2284 continue;
2285
2286 fltr_promisc_mask |=
2287 ice_determine_promisc_mask(&itr->fltr_info);
2288
2289 /* Skip if filter is not completely specified by given mask */
2290 if (fltr_promisc_mask & ~promisc_mask)
2291 continue;
2292
2293 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
2294 &remove_list_head,
2295 &itr->fltr_info);
2296 if (status) {
2297 mutex_unlock(rule_lock);
2298 goto free_fltr_list;
2299 }
2300 }
2301 mutex_unlock(rule_lock);
2302
2303 status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
2304
2305free_fltr_list:
2306 list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
2307 list_del(&fm_entry->list_entry);
2308 devm_kfree(ice_hw_to_dev(hw), fm_entry);
2309 }
2310
2311 return status;
2312}
2313
2314/**
2315 * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
2316 * @hw: pointer to the hardware structure
2317 * @vsi_handle: VSI handle to configure
2318 * @promisc_mask: mask of promiscuous config bits
2319 * @vid: VLAN ID to set VLAN promiscuous
2320 */
2321enum ice_status
2322ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
2323{
2324 enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
2325 struct ice_fltr_list_entry f_list_entry;
2326 struct ice_fltr_info new_fltr;
2327 enum ice_status status = 0;
2328 bool is_tx_fltr;
2329 u16 hw_vsi_id;
2330 int pkt_type;
2331 u8 recipe_id;
2332
2333 if (!ice_is_vsi_valid(hw, vsi_handle))
2334 return ICE_ERR_PARAM;
2335 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2336
2337 memset(&new_fltr, 0, sizeof(new_fltr));
2338
2339 if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
2340 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
2341 new_fltr.l_data.mac_vlan.vlan_id = vid;
2342 recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
2343 } else {
2344 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
2345 recipe_id = ICE_SW_LKUP_PROMISC;
2346 }
2347
2348 /* Separate filters must be set for each direction/packet type
2349 * combination, so we will loop over the mask value, store the
2350 * individual type, and clear it out in the input mask as it
2351 * is found.
2352 */
2353 while (promisc_mask) {
2354 u8 *mac_addr;
2355
2356 pkt_type = 0;
2357 is_tx_fltr = false;
2358
2359 if (promisc_mask & ICE_PROMISC_UCAST_RX) {
2360 promisc_mask &= ~ICE_PROMISC_UCAST_RX;
2361 pkt_type = UCAST_FLTR;
2362 } else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
2363 promisc_mask &= ~ICE_PROMISC_UCAST_TX;
2364 pkt_type = UCAST_FLTR;
2365 is_tx_fltr = true;
2366 } else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
2367 promisc_mask &= ~ICE_PROMISC_MCAST_RX;
2368 pkt_type = MCAST_FLTR;
2369 } else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
2370 promisc_mask &= ~ICE_PROMISC_MCAST_TX;
2371 pkt_type = MCAST_FLTR;
2372 is_tx_fltr = true;
2373 } else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
2374 promisc_mask &= ~ICE_PROMISC_BCAST_RX;
2375 pkt_type = BCAST_FLTR;
2376 } else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
2377 promisc_mask &= ~ICE_PROMISC_BCAST_TX;
2378 pkt_type = BCAST_FLTR;
2379 is_tx_fltr = true;
2380 }
2381
2382 /* Check for VLAN promiscuous flag */
2383 if (promisc_mask & ICE_PROMISC_VLAN_RX) {
2384 promisc_mask &= ~ICE_PROMISC_VLAN_RX;
2385 } else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
2386 promisc_mask &= ~ICE_PROMISC_VLAN_TX;
2387 is_tx_fltr = true;
2388 }
2389
2390 /* Set filter DA based on packet type */
2391 mac_addr = new_fltr.l_data.mac.mac_addr;
2392 if (pkt_type == BCAST_FLTR) {
2393 eth_broadcast_addr(mac_addr);
2394 } else if (pkt_type == MCAST_FLTR ||
2395 pkt_type == UCAST_FLTR) {
2396 /* Use the dummy ether header DA */
2397 ether_addr_copy(mac_addr, dummy_eth_header);
2398 if (pkt_type == MCAST_FLTR)
2399 mac_addr[0] |= 0x1; /* Set multicast bit */
2400 }
2401
2402 /* Need to reset this to zero for all iterations */
2403 new_fltr.flag = 0;
2404 if (is_tx_fltr) {
2405 new_fltr.flag |= ICE_FLTR_TX;
2406 new_fltr.src = hw_vsi_id;
2407 } else {
2408 new_fltr.flag |= ICE_FLTR_RX;
2409 new_fltr.src = hw->port_info->lport;
2410 }
2411
2412 new_fltr.fltr_act = ICE_FWD_TO_VSI;
2413 new_fltr.vsi_handle = vsi_handle;
2414 new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
2415 f_list_entry.fltr_info = new_fltr;
2416
2417 status = ice_add_rule_internal(hw, recipe_id, &f_list_entry);
2418 if (status)
2419 goto set_promisc_exit;
2420 }
2421
2422set_promisc_exit:
2423 return status;
2424}
2425
2426/**
2427 * ice_set_vlan_vsi_promisc
2428 * @hw: pointer to the hardware structure
2429 * @vsi_handle: VSI handle to configure
2430 * @promisc_mask: mask of promiscuous config bits
2431 * @rm_vlan_promisc: Clear VLANs VSI promisc mode
2432 *
2433 * Configure VSI with all associated VLANs to given promiscuous mode(s)
2434 */
2435enum ice_status
2436ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
2437 bool rm_vlan_promisc)
2438{
2439 struct ice_switch_info *sw = hw->switch_info;
2440 struct ice_fltr_list_entry *list_itr, *tmp;
2441 struct list_head vsi_list_head;
2442 struct list_head *vlan_head;
2443 struct mutex *vlan_lock; /* Lock to protect filter rule list */
2444 enum ice_status status;
2445 u16 vlan_id;
2446
2447 INIT_LIST_HEAD(&vsi_list_head);
2448 vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
2449 vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
2450 mutex_lock(vlan_lock);
2451 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
2452 &vsi_list_head);
2453 mutex_unlock(vlan_lock);
2454 if (status)
2455 goto free_fltr_list;
2456
2457 list_for_each_entry(list_itr, &vsi_list_head, list_entry) {
2458 vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
2459 if (rm_vlan_promisc)
2460 status = ice_clear_vsi_promisc(hw, vsi_handle,
2461 promisc_mask, vlan_id);
2462 else
2463 status = ice_set_vsi_promisc(hw, vsi_handle,
2464 promisc_mask, vlan_id);
2465 if (status)
2466 break;
2467 }
2468
2469free_fltr_list:
2470 list_for_each_entry_safe(list_itr, tmp, &vsi_list_head, list_entry) {
2471 list_del(&list_itr->list_entry);
2472 devm_kfree(ice_hw_to_dev(hw), list_itr);
2473 }
2474 return status;
2475}
2476
2477/**
2193 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI 2478 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
2194 * @hw: pointer to the hardware structure 2479 * @hw: pointer to the hardware structure
2195 * @vsi_handle: VSI handle to remove filters from 2480 * @vsi_handle: VSI handle to remove filters from
@@ -2224,12 +2509,14 @@ ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
2224 case ICE_SW_LKUP_VLAN: 2509 case ICE_SW_LKUP_VLAN:
2225 ice_remove_vlan(hw, &remove_list_head); 2510 ice_remove_vlan(hw, &remove_list_head);
2226 break; 2511 break;
2512 case ICE_SW_LKUP_PROMISC:
2513 case ICE_SW_LKUP_PROMISC_VLAN:
2514 ice_remove_promisc(hw, lkup, &remove_list_head);
2515 break;
2227 case ICE_SW_LKUP_MAC_VLAN: 2516 case ICE_SW_LKUP_MAC_VLAN:
2228 case ICE_SW_LKUP_ETHERTYPE: 2517 case ICE_SW_LKUP_ETHERTYPE:
2229 case ICE_SW_LKUP_ETHERTYPE_MAC: 2518 case ICE_SW_LKUP_ETHERTYPE_MAC:
2230 case ICE_SW_LKUP_PROMISC:
2231 case ICE_SW_LKUP_DFLT: 2519 case ICE_SW_LKUP_DFLT:
2232 case ICE_SW_LKUP_PROMISC_VLAN:
2233 case ICE_SW_LKUP_LAST: 2520 case ICE_SW_LKUP_LAST:
2234 default: 2521 default:
2235 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup); 2522 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup);