linux/drivers/net/ethernet/intel/ice/ice_fltr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (C) 2018-2020, Intel Corporation. */
   3
   4#include "ice.h"
   5#include "ice_fltr.h"
   6
   7/**
   8 * ice_fltr_free_list - free filter lists helper
   9 * @dev: pointer to the device struct
  10 * @h: pointer to the list head to be freed
  11 *
  12 * Helper function to free filter lists previously created using
  13 * ice_fltr_add_mac_to_list
  14 */
  15void ice_fltr_free_list(struct device *dev, struct list_head *h)
  16{
  17        struct ice_fltr_list_entry *e, *tmp;
  18
  19        list_for_each_entry_safe(e, tmp, h, list_entry) {
  20                list_del(&e->list_entry);
  21                devm_kfree(dev, e);
  22        }
  23}
  24
  25/**
  26 * ice_fltr_add_entry_to_list - allocate and add filter entry to list
  27 * @dev: pointer to device needed by alloc function
  28 * @info: filter info struct that gets added to the passed in list
  29 * @list: pointer to the list which contains MAC filters entry
  30 */
  31static int
  32ice_fltr_add_entry_to_list(struct device *dev, struct ice_fltr_info *info,
  33                           struct list_head *list)
  34{
  35        struct ice_fltr_list_entry *entry;
  36
  37        entry = devm_kzalloc(dev, sizeof(*entry), GFP_ATOMIC);
  38        if (!entry)
  39                return -ENOMEM;
  40
  41        entry->fltr_info = *info;
  42
  43        INIT_LIST_HEAD(&entry->list_entry);
  44        list_add(&entry->list_entry, list);
  45
  46        return 0;
  47}
  48
  49/**
  50 * ice_fltr_add_mac_list - add list of MAC filters
  51 * @vsi: pointer to VSI struct
  52 * @list: list of filters
  53 */
  54enum ice_status
  55ice_fltr_add_mac_list(struct ice_vsi *vsi, struct list_head *list)
  56{
  57        return ice_add_mac(&vsi->back->hw, list);
  58}
  59
  60/**
  61 * ice_fltr_remove_mac_list - remove list of MAC filters
  62 * @vsi: pointer to VSI struct
  63 * @list: list of filters
  64 */
  65enum ice_status
  66ice_fltr_remove_mac_list(struct ice_vsi *vsi, struct list_head *list)
  67{
  68        return ice_remove_mac(&vsi->back->hw, list);
  69}
  70
  71/**
  72 * ice_fltr_add_vlan_list - add list of VLAN filters
  73 * @vsi: pointer to VSI struct
  74 * @list: list of filters
  75 */
  76static enum ice_status
  77ice_fltr_add_vlan_list(struct ice_vsi *vsi, struct list_head *list)
  78{
  79        return ice_add_vlan(&vsi->back->hw, list);
  80}
  81
  82/**
  83 * ice_fltr_remove_vlan_list - remove list of VLAN filters
  84 * @vsi: pointer to VSI struct
  85 * @list: list of filters
  86 */
  87static enum ice_status
  88ice_fltr_remove_vlan_list(struct ice_vsi *vsi, struct list_head *list)
  89{
  90        return ice_remove_vlan(&vsi->back->hw, list);
  91}
  92
  93/**
  94 * ice_fltr_add_eth_list - add list of ethertype filters
  95 * @vsi: pointer to VSI struct
  96 * @list: list of filters
  97 */
  98static enum ice_status
  99ice_fltr_add_eth_list(struct ice_vsi *vsi, struct list_head *list)
 100{
 101        return ice_add_eth_mac(&vsi->back->hw, list);
 102}
 103
 104/**
 105 * ice_fltr_remove_eth_list - remove list of ethertype filters
 106 * @vsi: pointer to VSI struct
 107 * @list: list of filters
 108 */
 109static enum ice_status
 110ice_fltr_remove_eth_list(struct ice_vsi *vsi, struct list_head *list)
 111{
 112        return ice_remove_eth_mac(&vsi->back->hw, list);
 113}
 114
 115/**
 116 * ice_fltr_remove_all - remove all filters associated with VSI
 117 * @vsi: pointer to VSI struct
 118 */
 119void ice_fltr_remove_all(struct ice_vsi *vsi)
 120{
 121        ice_remove_vsi_fltr(&vsi->back->hw, vsi->idx);
 122}
 123
 124/**
 125 * ice_fltr_add_mac_to_list - add MAC filter info to exsisting list
 126 * @vsi: pointer to VSI struct
 127 * @list: list to add filter info to
 128 * @mac: MAC address to add
 129 * @action: filter action
 130 */
 131int
 132ice_fltr_add_mac_to_list(struct ice_vsi *vsi, struct list_head *list,
 133                         const u8 *mac, enum ice_sw_fwd_act_type action)
 134{
 135        struct ice_fltr_info info = { 0 };
 136
 137        info.flag = ICE_FLTR_TX;
 138        info.src_id = ICE_SRC_ID_VSI;
 139        info.lkup_type = ICE_SW_LKUP_MAC;
 140        info.fltr_act = action;
 141        info.vsi_handle = vsi->idx;
 142
 143        ether_addr_copy(info.l_data.mac.mac_addr, mac);
 144
 145        return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,
 146                                          list);
 147}
 148
 149/**
 150 * ice_fltr_add_vlan_to_list - add VLAN filter info to exsisting list
 151 * @vsi: pointer to VSI struct
 152 * @list: list to add filter info to
 153 * @vlan_id: VLAN ID to add
 154 * @action: filter action
 155 */
 156static int
 157ice_fltr_add_vlan_to_list(struct ice_vsi *vsi, struct list_head *list,
 158                          u16 vlan_id, enum ice_sw_fwd_act_type action)
 159{
 160        struct ice_fltr_info info = { 0 };
 161
 162        info.flag = ICE_FLTR_TX;
 163        info.src_id = ICE_SRC_ID_VSI;
 164        info.lkup_type = ICE_SW_LKUP_VLAN;
 165        info.fltr_act = action;
 166        info.vsi_handle = vsi->idx;
 167        info.l_data.vlan.vlan_id = vlan_id;
 168
 169        return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,
 170                                          list);
 171}
 172
 173/**
 174 * ice_fltr_add_eth_to_list - add ethertype filter info to exsisting list
 175 * @vsi: pointer to VSI struct
 176 * @list: list to add filter info to
 177 * @ethertype: ethertype of packet that matches filter
 178 * @flag: filter direction, Tx or Rx
 179 * @action: filter action
 180 */
 181static int
 182ice_fltr_add_eth_to_list(struct ice_vsi *vsi, struct list_head *list,
 183                         u16 ethertype, u16 flag,
 184                         enum ice_sw_fwd_act_type action)
 185{
 186        struct ice_fltr_info info = { 0 };
 187
 188        info.flag = flag;
 189        info.lkup_type = ICE_SW_LKUP_ETHERTYPE;
 190        info.fltr_act = action;
 191        info.vsi_handle = vsi->idx;
 192        info.l_data.ethertype_mac.ethertype = ethertype;
 193
 194        if (flag == ICE_FLTR_TX)
 195                info.src_id = ICE_SRC_ID_VSI;
 196        else
 197                info.src_id = ICE_SRC_ID_LPORT;
 198
 199        return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,
 200                                          list);
 201}
 202
 203/**
 204 * ice_fltr_prepare_mac - add or remove MAC rule
 205 * @vsi: pointer to VSI struct
 206 * @mac: MAC address to add
 207 * @action: action to be performed on filter match
 208 * @mac_action: pointer to add or remove MAC function
 209 */
 210static enum ice_status
 211ice_fltr_prepare_mac(struct ice_vsi *vsi, const u8 *mac,
 212                     enum ice_sw_fwd_act_type action,
 213                     enum ice_status (*mac_action)(struct ice_vsi *,
 214                                                   struct list_head *))
 215{
 216        enum ice_status result;
 217        LIST_HEAD(tmp_list);
 218
 219        if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action)) {
 220                ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
 221                return ICE_ERR_NO_MEMORY;
 222        }
 223
 224        result = mac_action(vsi, &tmp_list);
 225        ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
 226        return result;
 227}
 228
 229/**
 230 * ice_fltr_prepare_mac_and_broadcast - add or remove MAC and broadcast filter
 231 * @vsi: pointer to VSI struct
 232 * @mac: MAC address to add
 233 * @action: action to be performed on filter match
 234 * @mac_action: pointer to add or remove MAC function
 235 */
 236static enum ice_status
 237ice_fltr_prepare_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac,
 238                                   enum ice_sw_fwd_act_type action,
 239                                   enum ice_status(*mac_action)
 240                                   (struct ice_vsi *, struct list_head *))
 241{
 242        u8 broadcast[ETH_ALEN];
 243        enum ice_status result;
 244        LIST_HEAD(tmp_list);
 245
 246        eth_broadcast_addr(broadcast);
 247        if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action) ||
 248            ice_fltr_add_mac_to_list(vsi, &tmp_list, broadcast, action)) {
 249                ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
 250                return ICE_ERR_NO_MEMORY;
 251        }
 252
 253        result = mac_action(vsi, &tmp_list);
 254        ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
 255        return result;
 256}
 257
 258/**
 259 * ice_fltr_prepare_vlan - add or remove VLAN filter
 260 * @vsi: pointer to VSI struct
 261 * @vlan_id: VLAN ID to add
 262 * @action: action to be performed on filter match
 263 * @vlan_action: pointer to add or remove VLAN function
 264 */
 265static enum ice_status
 266ice_fltr_prepare_vlan(struct ice_vsi *vsi, u16 vlan_id,
 267                      enum ice_sw_fwd_act_type action,
 268                      enum ice_status (*vlan_action)(struct ice_vsi *,
 269                                                     struct list_head *))
 270{
 271        enum ice_status result;
 272        LIST_HEAD(tmp_list);
 273
 274        if (ice_fltr_add_vlan_to_list(vsi, &tmp_list, vlan_id, action))
 275                return ICE_ERR_NO_MEMORY;
 276
 277        result = vlan_action(vsi, &tmp_list);
 278        ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
 279        return result;
 280}
 281
 282/**
 283 * ice_fltr_prepare_eth - add or remove ethertype filter
 284 * @vsi: pointer to VSI struct
 285 * @ethertype: ethertype of packet to be filtered
 286 * @flag: direction of packet, Tx or Rx
 287 * @action: action to be performed on filter match
 288 * @eth_action: pointer to add or remove ethertype function
 289 */
 290static enum ice_status
 291ice_fltr_prepare_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,
 292                     enum ice_sw_fwd_act_type action,
 293                     enum ice_status (*eth_action)(struct ice_vsi *,
 294                                                   struct list_head *))
 295{
 296        enum ice_status result;
 297        LIST_HEAD(tmp_list);
 298
 299        if (ice_fltr_add_eth_to_list(vsi, &tmp_list, ethertype, flag, action))
 300                return ICE_ERR_NO_MEMORY;
 301
 302        result = eth_action(vsi, &tmp_list);
 303        ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
 304        return result;
 305}
 306
 307/**
 308 * ice_fltr_add_mac - add single MAC filter
 309 * @vsi: pointer to VSI struct
 310 * @mac: MAC to add
 311 * @action: action to be performed on filter match
 312 */
 313enum ice_status ice_fltr_add_mac(struct ice_vsi *vsi, const u8 *mac,
 314                                 enum ice_sw_fwd_act_type action)
 315{
 316        return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_add_mac_list);
 317}
 318
 319/**
 320 * ice_fltr_add_mac_and_broadcast - add single MAC and broadcast
 321 * @vsi: pointer to VSI struct
 322 * @mac: MAC to add
 323 * @action: action to be performed on filter match
 324 */
 325enum ice_status
 326ice_fltr_add_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac,
 327                               enum ice_sw_fwd_act_type action)
 328{
 329        return ice_fltr_prepare_mac_and_broadcast(vsi, mac, action,
 330                                                  ice_fltr_add_mac_list);
 331}
 332
 333/**
 334 * ice_fltr_remove_mac - remove MAC filter
 335 * @vsi: pointer to VSI struct
 336 * @mac: filter MAC to remove
 337 * @action: action to remove
 338 */
 339enum ice_status ice_fltr_remove_mac(struct ice_vsi *vsi, const u8 *mac,
 340                                    enum ice_sw_fwd_act_type action)
 341{
 342        return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_remove_mac_list);
 343}
 344
 345/**
 346 * ice_fltr_add_vlan - add single VLAN filter
 347 * @vsi: pointer to VSI struct
 348 * @vlan_id: VLAN ID to add
 349 * @action: action to be performed on filter match
 350 */
 351enum ice_status ice_fltr_add_vlan(struct ice_vsi *vsi, u16 vlan_id,
 352                                  enum ice_sw_fwd_act_type action)
 353{
 354        return ice_fltr_prepare_vlan(vsi, vlan_id, action,
 355                                     ice_fltr_add_vlan_list);
 356}
 357
 358/**
 359 * ice_fltr_remove_vlan - remove VLAN filter
 360 * @vsi: pointer to VSI struct
 361 * @vlan_id: filter VLAN to remove
 362 * @action: action to remove
 363 */
 364enum ice_status ice_fltr_remove_vlan(struct ice_vsi *vsi, u16 vlan_id,
 365                                     enum ice_sw_fwd_act_type action)
 366{
 367        return ice_fltr_prepare_vlan(vsi, vlan_id, action,
 368                                     ice_fltr_remove_vlan_list);
 369}
 370
 371/**
 372 * ice_fltr_add_eth - add specyfic ethertype filter
 373 * @vsi: pointer to VSI struct
 374 * @ethertype: ethertype of filter
 375 * @flag: direction of packet to be filtered, Tx or Rx
 376 * @action: action to be performed on filter match
 377 */
 378enum ice_status ice_fltr_add_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,
 379                                 enum ice_sw_fwd_act_type action)
 380{
 381        return ice_fltr_prepare_eth(vsi, ethertype, flag, action,
 382                                    ice_fltr_add_eth_list);
 383}
 384
 385/**
 386 * ice_fltr_remove_eth - remove ethertype filter
 387 * @vsi: pointer to VSI struct
 388 * @ethertype: ethertype of filter
 389 * @flag: direction of filter
 390 * @action: action to remove
 391 */
 392enum ice_status ice_fltr_remove_eth(struct ice_vsi *vsi, u16 ethertype,
 393                                    u16 flag, enum ice_sw_fwd_act_type action)
 394{
 395        return ice_fltr_prepare_eth(vsi, ethertype, flag, action,
 396                                    ice_fltr_remove_eth_list);
 397}
 398