[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <MW4PR11MB577640F5292E101BE51FCE02FD22A@MW4PR11MB5776.namprd11.prod.outlook.com>
Date: Thu, 22 Jun 2023 12:55:46 +0000
From: "Drewek, Wojciech" <wojciech.drewek@...el.com>
To: Vlad Buslov <vladbu@...dia.com>, "Nguyen, Anthony L"
<anthony.l.nguyen@...el.com>
CC: "davem@...emloft.net" <davem@...emloft.net>, "kuba@...nel.org"
<kuba@...nel.org>, "pabeni@...hat.com" <pabeni@...hat.com>,
"edumazet@...gle.com" <edumazet@...gle.com>, "netdev@...r.kernel.org"
<netdev@...r.kernel.org>, "jiri@...nulli.us" <jiri@...nulli.us>, ivecera
<ivecera@...hat.com>, "simon.horman@...igine.com"
<simon.horman@...igine.com>, "Buvaneswaran, Sujai"
<sujai.buvaneswaran@...el.com>
Subject: RE: [PATCH net-next 07/12] ice: Switchdev FDB events support
> -----Original Message-----
> From: Vlad Buslov <vladbu@...dia.com>
> Sent: czwartek, 22 czerwca 2023 13:54
> To: Nguyen, Anthony L <anthony.l.nguyen@...el.com>
> Cc: davem@...emloft.net; kuba@...nel.org; pabeni@...hat.com; edumazet@...gle.com; netdev@...r.kernel.org; Drewek,
> Wojciech <wojciech.drewek@...el.com>; jiri@...nulli.us; ivecera <ivecera@...hat.com>; simon.horman@...igine.com;
> Buvaneswaran, Sujai <sujai.buvaneswaran@...el.com>
> Subject: Re: [PATCH net-next 07/12] ice: Switchdev FDB events support
>
> On Tue 20 Jun 2023 at 10:44, Tony Nguyen <anthony.l.nguyen@...el.com> wrote:
> > From: Wojciech Drewek <wojciech.drewek@...el.com>
> >
> > Listen for SWITCHDEV_FDB_{ADD|DEL}_TO_DEVICE events while in switchdev
> > mode. Accept these events on both uplink and VF PR ports. Add HW
> > rules in newly created workqueue. FDB entries are stored in rhashtable
> > for lookup when removing the entry and in the list for cleanup
> > purpose. Direction of the HW rule depends on the type of the ports
> > on which the FDB event was received:
> >
> > ICE_ESWITCH_BR_UPLINK_PORT:
> > TX rule that forwards the packet to the LAN (egress).
> >
> > ICE_ESWITCH_BR_VF_REPR_PORT:
> > RX rule that forwards the packet to the VF associated
> > with the port representor.
>
> Just to clarify, does this implementation support offloading of VF-to-VF
> traffic?
Yes
>
> >
> > In both cases the rule matches on the dst mac address.
> > All the FDB entries are stored in the bridge structure.
> > When the port is removed all the FDB entries associated with
> > this port are removed as well. This is achieved thanks to the reference
> > to the port that FDB entry holds.
> >
> > In the fwd rule we use only one lookup type (MAC address)
> > but lkups_cnt variable is already introduced because
> > we will have more lookups in the subsequent patches.
> >
> > Signed-off-by: Wojciech Drewek <wojciech.drewek@...el.com>
> > Tested-by: Sujai Buvaneswaran <sujai.buvaneswaran@...el.com>
> > Signed-off-by: Tony Nguyen <anthony.l.nguyen@...el.com>
> > ---
> > .../net/ethernet/intel/ice/ice_eswitch_br.c | 439 +++++++++++++++++-
> > .../net/ethernet/intel/ice/ice_eswitch_br.h | 46 ++
> > 2 files changed, 484 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c
> > index 8b9ab68dfd53..8f22da490a69 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c
> > +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c
> > @@ -4,6 +4,14 @@
> > #include "ice.h"
> > #include "ice_eswitch_br.h"
> > #include "ice_repr.h"
> > +#include "ice_switch.h"
> > +
> > +static const struct rhashtable_params ice_fdb_ht_params = {
> > + .key_offset = offsetof(struct ice_esw_br_fdb_entry, data),
> > + .key_len = sizeof(struct ice_esw_br_fdb_data),
> > + .head_offset = offsetof(struct ice_esw_br_fdb_entry, ht_node),
> > + .automatic_shrinking = true,
> > +};
> >
> > static bool ice_eswitch_br_is_dev_valid(const struct net_device *dev)
> > {
> > @@ -27,15 +35,412 @@ ice_eswitch_br_netdev_to_port(struct net_device *dev)
> > return NULL;
> > }
> >
> > +static void
> > +ice_eswitch_br_ingress_rule_setup(struct ice_adv_rule_info *rule_info,
> > + u8 pf_id, u16 vf_vsi_idx)
> > +{
> > + rule_info->sw_act.vsi_handle = vf_vsi_idx;
> > + rule_info->sw_act.flag |= ICE_FLTR_RX;
> > + rule_info->sw_act.src = pf_id;
> > + rule_info->priority = 5;
> > +}
> > +
> > +static void
> > +ice_eswitch_br_egress_rule_setup(struct ice_adv_rule_info *rule_info,
> > + u16 pf_vsi_idx)
> > +{
> > + rule_info->sw_act.vsi_handle = pf_vsi_idx;
> > + rule_info->sw_act.flag |= ICE_FLTR_TX;
> > + rule_info->flags_info.act = ICE_SINGLE_ACT_LAN_ENABLE;
> > + rule_info->flags_info.act_valid = true;
> > + rule_info->priority = 5;
> > +}
> > +
> > +static int
> > +ice_eswitch_br_rule_delete(struct ice_hw *hw, struct ice_rule_query_data *rule)
> > +{
> > + int err;
> > +
> > + if (!rule)
> > + return -EINVAL;
> > +
> > + err = ice_rem_adv_rule_by_id(hw, rule);
> > + kfree(rule);
> > +
> > + return err;
> > +}
> > +
> > +static struct ice_rule_query_data *
> > +ice_eswitch_br_fwd_rule_create(struct ice_hw *hw, int vsi_idx, int port_type,
> > + const unsigned char *mac)
> > +{
> > + struct ice_adv_rule_info rule_info = { 0 };
> > + struct ice_rule_query_data *rule;
> > + struct ice_adv_lkup_elem *list;
> > + u16 lkups_cnt = 1;
> > + int err;
> > +
> > + rule = kzalloc(sizeof(*rule), GFP_KERNEL);
> > + if (!rule)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + list = kcalloc(lkups_cnt, sizeof(*list), GFP_ATOMIC);
> > + if (!list) {
> > + err = -ENOMEM;
> > + goto err_list_alloc;
> > + }
> > +
> > + switch (port_type) {
> > + case ICE_ESWITCH_BR_UPLINK_PORT:
> > + ice_eswitch_br_egress_rule_setup(&rule_info, vsi_idx);
> > + break;
> > + case ICE_ESWITCH_BR_VF_REPR_PORT:
> > + ice_eswitch_br_ingress_rule_setup(&rule_info, hw->pf_id,
> > + vsi_idx);
> > + break;
> > + default:
> > + err = -EINVAL;
> > + goto err_add_rule;
> > + }
> > +
> > + list[0].type = ICE_MAC_OFOS;
> > + ether_addr_copy(list[0].h_u.eth_hdr.dst_addr, mac);
> > + eth_broadcast_addr(list[0].m_u.eth_hdr.dst_addr);
> > +
> > + rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI;
> > +
> > + err = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, rule);
> > + if (err)
> > + goto err_add_rule;
> > +
> > + kfree(list);
> > +
> > + return rule;
> > +
> > +err_add_rule:
> > + kfree(list);
> > +err_list_alloc:
> > + kfree(rule);
> > +
> > + return ERR_PTR(err);
> > +}
> > +
> > +static struct ice_esw_br_flow *
> > +ice_eswitch_br_flow_create(struct device *dev, struct ice_hw *hw, int vsi_idx,
> > + int port_type, const unsigned char *mac)
> > +{
> > + struct ice_rule_query_data *fwd_rule;
> > + struct ice_esw_br_flow *flow;
> > + int err;
> > +
> > + flow = kzalloc(sizeof(*flow), GFP_KERNEL);
> > + if (!flow)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + fwd_rule = ice_eswitch_br_fwd_rule_create(hw, vsi_idx, port_type, mac);
> > + err = PTR_ERR_OR_ZERO(fwd_rule);
> > + if (err) {
> > + dev_err(dev, "Failed to create eswitch bridge %sgress forward rule, err: %d\n",
> > + port_type == ICE_ESWITCH_BR_UPLINK_PORT ? "e" : "in",
> > + err);
> > + goto err_fwd_rule;
> > + }
> > +
> > + flow->fwd_rule = fwd_rule;
> > +
> > + return flow;
> > +
> > +err_fwd_rule:
> > + kfree(flow);
> > +
> > + return ERR_PTR(err);
> > +}
> > +
> > +static struct ice_esw_br_fdb_entry *
> > +ice_eswitch_br_fdb_find(struct ice_esw_br *bridge, const unsigned char *mac,
> > + u16 vid)
> > +{
> > + struct ice_esw_br_fdb_data data = {
> > + .vid = vid,
> > + };
> > +
> > + ether_addr_copy(data.addr, mac);
> > + return rhashtable_lookup_fast(&bridge->fdb_ht, &data,
> > + ice_fdb_ht_params);
> > +}
> > +
> > +static void
> > +ice_eswitch_br_flow_delete(struct ice_pf *pf, struct ice_esw_br_flow *flow)
> > +{
> > + struct device *dev = ice_pf_to_dev(pf);
> > + int err;
> > +
> > + err = ice_eswitch_br_rule_delete(&pf->hw, flow->fwd_rule);
> > + if (err)
> > + dev_err(dev, "Failed to delete FDB forward rule, err: %d\n",
> > + err);
> > +
> > + kfree(flow);
> > +}
> > +
> > +static void
> > +ice_eswitch_br_fdb_entry_delete(struct ice_esw_br *bridge,
> > + struct ice_esw_br_fdb_entry *fdb_entry)
> > +{
> > + struct ice_pf *pf = bridge->br_offloads->pf;
> > +
> > + rhashtable_remove_fast(&bridge->fdb_ht, &fdb_entry->ht_node,
> > + ice_fdb_ht_params);
> > + list_del(&fdb_entry->list);
> > +
> > + ice_eswitch_br_flow_delete(pf, fdb_entry->flow);
> > +
> > + kfree(fdb_entry);
> > +}
> > +
> > +static void
> > +ice_eswitch_br_fdb_offload_notify(struct net_device *dev,
> > + const unsigned char *mac, u16 vid,
> > + unsigned long val)
> > +{
> > + struct switchdev_notifier_fdb_info fdb_info = {
> > + .addr = mac,
> > + .vid = vid,
> > + .offloaded = true,
> > + };
> > +
> > + call_switchdev_notifiers(val, dev, &fdb_info.info, NULL);
> > +}
> > +
> > +static void
> > +ice_eswitch_br_fdb_entry_notify_and_cleanup(struct ice_esw_br *bridge,
> > + struct ice_esw_br_fdb_entry *entry)
> > +{
> > + if (!(entry->flags & ICE_ESWITCH_BR_FDB_ADDED_BY_USER))
> > + ice_eswitch_br_fdb_offload_notify(entry->dev, entry->data.addr,
> > + entry->data.vid,
> > + SWITCHDEV_FDB_DEL_TO_BRIDGE);
> > + ice_eswitch_br_fdb_entry_delete(bridge, entry);
> > +}
> > +
> > +static void
> > +ice_eswitch_br_fdb_entry_find_and_delete(struct ice_esw_br *bridge,
> > + const unsigned char *mac, u16 vid)
> > +{
> > + struct ice_pf *pf = bridge->br_offloads->pf;
> > + struct ice_esw_br_fdb_entry *fdb_entry;
> > + struct device *dev = ice_pf_to_dev(pf);
> > +
> > + fdb_entry = ice_eswitch_br_fdb_find(bridge, mac, vid);
> > + if (!fdb_entry) {
> > + dev_err(dev, "FDB entry with mac: %pM and vid: %u not found\n",
> > + mac, vid);
> > + return;
> > + }
> > +
> > + ice_eswitch_br_fdb_entry_notify_and_cleanup(bridge, fdb_entry);
> > +}
> > +
> > +static void
> > +ice_eswitch_br_fdb_entry_create(struct net_device *netdev,
> > + struct ice_esw_br_port *br_port,
> > + bool added_by_user,
> > + const unsigned char *mac, u16 vid)
> > +{
> > + struct ice_esw_br *bridge = br_port->bridge;
> > + struct ice_pf *pf = bridge->br_offloads->pf;
> > + struct device *dev = ice_pf_to_dev(pf);
> > + struct ice_esw_br_fdb_entry *fdb_entry;
> > + struct ice_esw_br_flow *flow;
> > + struct ice_hw *hw = &pf->hw;
> > + unsigned long event;
> > + int err;
> > +
> > + fdb_entry = ice_eswitch_br_fdb_find(bridge, mac, vid);
> > + if (fdb_entry)
> > + ice_eswitch_br_fdb_entry_notify_and_cleanup(bridge, fdb_entry);
> > +
> > + fdb_entry = kzalloc(sizeof(*fdb_entry), GFP_KERNEL);
> > + if (!fdb_entry) {
> > + err = -ENOMEM;
> > + goto err_exit;
> > + }
> > +
> > + flow = ice_eswitch_br_flow_create(dev, hw, br_port->vsi_idx,
> > + br_port->type, mac);
> > + if (IS_ERR(flow)) {
> > + err = PTR_ERR(flow);
> > + goto err_add_flow;
> > + }
> > +
> > + ether_addr_copy(fdb_entry->data.addr, mac);
> > + fdb_entry->data.vid = vid;
> > + fdb_entry->br_port = br_port;
> > + fdb_entry->flow = flow;
> > + fdb_entry->dev = netdev;
> > + event = SWITCHDEV_FDB_ADD_TO_BRIDGE;
> > +
> > + if (added_by_user) {
> > + fdb_entry->flags |= ICE_ESWITCH_BR_FDB_ADDED_BY_USER;
> > + event = SWITCHDEV_FDB_OFFLOADED;
> > + }
> > +
> > + err = rhashtable_insert_fast(&bridge->fdb_ht, &fdb_entry->ht_node,
> > + ice_fdb_ht_params);
> > + if (err)
> > + goto err_fdb_insert;
> > +
> > + list_add(&fdb_entry->list, &bridge->fdb_list);
> > +
> > + ice_eswitch_br_fdb_offload_notify(netdev, mac, vid, event);
> > +
> > + return;
> > +
> > +err_fdb_insert:
> > + ice_eswitch_br_flow_delete(pf, flow);
> > +err_add_flow:
> > + kfree(fdb_entry);
> > +err_exit:
> > + dev_err(dev, "Failed to create fdb entry, err: %d\n", err);
> > +}
> > +
> > +static void
> > +ice_eswitch_br_fdb_work_dealloc(struct ice_esw_br_fdb_work *fdb_work)
> > +{
> > + kfree(fdb_work->fdb_info.addr);
> > + kfree(fdb_work);
> > +}
> > +
> > +static void
> > +ice_eswitch_br_fdb_event_work(struct work_struct *work)
> > +{
> > + struct ice_esw_br_fdb_work *fdb_work = ice_work_to_fdb_work(work);
> > + bool added_by_user = fdb_work->fdb_info.added_by_user;
> > + struct ice_esw_br_port *br_port = fdb_work->br_port;
> > + const unsigned char *mac = fdb_work->fdb_info.addr;
> > + u16 vid = fdb_work->fdb_info.vid;
> > +
> > + rtnl_lock();
> > +
> > + if (!br_port || !br_port->bridge)
> > + goto err_exit;
> > +
> > + switch (fdb_work->event) {
> > + case SWITCHDEV_FDB_ADD_TO_DEVICE:
> > + ice_eswitch_br_fdb_entry_create(fdb_work->dev, br_port,
> > + added_by_user, mac, vid);
> > + break;
> > + case SWITCHDEV_FDB_DEL_TO_DEVICE:
> > + ice_eswitch_br_fdb_entry_find_and_delete(br_port->bridge,
> > + mac, vid);
> > + break;
> > + default:
> > + goto err_exit;
> > + }
> > +
> > +err_exit:
> > + rtnl_unlock();
> > + dev_put(fdb_work->dev);
> > + ice_eswitch_br_fdb_work_dealloc(fdb_work);
> > +}
> > +
> > +static struct ice_esw_br_fdb_work *
> > +ice_eswitch_br_fdb_work_alloc(struct switchdev_notifier_fdb_info *fdb_info,
> > + struct ice_esw_br_port *br_port,
> > + struct net_device *dev,
> > + unsigned long event)
> > +{
> > + struct ice_esw_br_fdb_work *work;
> > + unsigned char *mac;
> > +
> > + work = kzalloc(sizeof(*work), GFP_ATOMIC);
> > + if (!work)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + INIT_WORK(&work->work, ice_eswitch_br_fdb_event_work);
> > + memcpy(&work->fdb_info, fdb_info, sizeof(work->fdb_info));
> > +
> > + mac = kzalloc(ETH_ALEN, GFP_ATOMIC);
> > + if (!mac) {
> > + kfree(work);
> > + return ERR_PTR(-ENOMEM);
> > + }
> > +
> > + ether_addr_copy(mac, fdb_info->addr);
> > + work->fdb_info.addr = mac;
> > + work->br_port = br_port;
> > + work->event = event;
> > + work->dev = dev;
> > +
> > + return work;
> > +}
> > +
> > +static int
> > +ice_eswitch_br_switchdev_event(struct notifier_block *nb,
> > + unsigned long event, void *ptr)
> > +{
> > + struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
> > + struct switchdev_notifier_fdb_info *fdb_info;
> > + struct switchdev_notifier_info *info = ptr;
> > + struct ice_esw_br_offloads *br_offloads;
> > + struct ice_esw_br_fdb_work *work;
> > + struct ice_esw_br_port *br_port;
> > + struct netlink_ext_ack *extack;
> > + struct net_device *upper;
> > +
> > + br_offloads = ice_nb_to_br_offloads(nb, switchdev_nb);
> > + extack = switchdev_notifier_info_to_extack(ptr);
> > +
> > + upper = netdev_master_upper_dev_get_rcu(dev);
> > + if (!upper)
> > + return NOTIFY_DONE;
> > +
> > + if (!netif_is_bridge_master(upper))
> > + return NOTIFY_DONE;
> > +
> > + if (!ice_eswitch_br_is_dev_valid(dev))
> > + return NOTIFY_DONE;
> > +
> > + br_port = ice_eswitch_br_netdev_to_port(dev);
> > + if (!br_port)
> > + return NOTIFY_DONE;
> > +
> > + switch (event) {
> > + case SWITCHDEV_FDB_ADD_TO_DEVICE:
> > + case SWITCHDEV_FDB_DEL_TO_DEVICE:
> > + fdb_info = container_of(info, typeof(*fdb_info), info);
> > +
> > + work = ice_eswitch_br_fdb_work_alloc(fdb_info, br_port, dev,
> > + event);
> > + if (IS_ERR(work)) {
> > + NL_SET_ERR_MSG_MOD(extack, "Failed to init switchdev fdb work");
> > + return notifier_from_errno(PTR_ERR(work));
> > + }
> > + dev_hold(dev);
> > +
> > + queue_work(br_offloads->wq, &work->work);
> > + break;
> > + default:
> > + break;
> > + }
> > + return NOTIFY_DONE;
> > +}
> > +
> > static void
> > ice_eswitch_br_port_deinit(struct ice_esw_br *bridge,
> > struct ice_esw_br_port *br_port)
> > {
> > + struct ice_esw_br_fdb_entry *fdb_entry, *tmp;
> > struct ice_vsi *vsi = br_port->vsi;
> >
> > + list_for_each_entry_safe(fdb_entry, tmp, &bridge->fdb_list, list) {
> > + if (br_port == fdb_entry->br_port)
> > + ice_eswitch_br_fdb_entry_delete(bridge, fdb_entry);
> > + }
> > +
> > if (br_port->type == ICE_ESWITCH_BR_UPLINK_PORT && vsi->back)
> > vsi->back->br_port = NULL;
> > - else if (vsi->vf)
> > + else if (vsi->vf && vsi->vf->repr)
>
> Shouldn't this check be in the previous patch? Don't see anything that
> would influence this pointer assignment in this patch.
Yes, you're right. Small fix was squashed into wrong patch.
>
> > vsi->vf->repr->br_port = NULL;
> >
> > xa_erase(&bridge->ports, br_port->vsi_idx);
> > @@ -129,6 +534,8 @@ ice_eswitch_br_deinit(struct ice_esw_br_offloads *br_offloads,
> > ice_eswitch_br_ports_flush(bridge);
> > WARN_ON(!xa_empty(&bridge->ports));
> > xa_destroy(&bridge->ports);
> > + rhashtable_destroy(&bridge->fdb_ht);
> > +
> > br_offloads->bridge = NULL;
> > kfree(bridge);
> > }
> > @@ -137,11 +544,19 @@ static struct ice_esw_br *
> > ice_eswitch_br_init(struct ice_esw_br_offloads *br_offloads, int ifindex)
> > {
> > struct ice_esw_br *bridge;
> > + int err;
> >
> > bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
> > if (!bridge)
> > return ERR_PTR(-ENOMEM);
> >
> > + err = rhashtable_init(&bridge->fdb_ht, &ice_fdb_ht_params);
> > + if (err) {
> > + kfree(bridge);
> > + return ERR_PTR(err);
> > + }
> > +
> > + INIT_LIST_HEAD(&bridge->fdb_list);
> > bridge->br_offloads = br_offloads;
> > bridge->ifindex = ifindex;
> > xa_init(&bridge->ports);
> > @@ -340,6 +755,8 @@ ice_eswitch_br_offloads_deinit(struct ice_pf *pf)
> > return;
> >
> > unregister_netdevice_notifier(&br_offloads->netdev_nb);
> > + unregister_switchdev_notifier(&br_offloads->switchdev_nb);
> > + destroy_workqueue(br_offloads->wq);
> > /* Although notifier block is unregistered just before,
> > * so we don't get any new events, some events might be
> > * already in progress. Hold the rtnl lock and wait for
> > @@ -365,6 +782,22 @@ ice_eswitch_br_offloads_init(struct ice_pf *pf)
> > return PTR_ERR(br_offloads);
> > }
> >
> > + br_offloads->wq = alloc_ordered_workqueue("ice_bridge_wq", 0);
> > + if (!br_offloads->wq) {
> > + err = -ENOMEM;
> > + dev_err(dev, "Failed to allocate bridge workqueue\n");
> > + goto err_alloc_wq;
> > + }
> > +
> > + br_offloads->switchdev_nb.notifier_call =
> > + ice_eswitch_br_switchdev_event;
> > + err = register_switchdev_notifier(&br_offloads->switchdev_nb);
> > + if (err) {
> > + dev_err(dev,
> > + "Failed to register switchdev notifier\n");
> > + goto err_reg_switchdev_nb;
> > + }
> > +
> > br_offloads->netdev_nb.notifier_call = ice_eswitch_br_port_event;
> > err = register_netdevice_notifier(&br_offloads->netdev_nb);
> > if (err) {
> > @@ -376,6 +809,10 @@ ice_eswitch_br_offloads_init(struct ice_pf *pf)
> > return 0;
> >
> > err_reg_netdev_nb:
> > + unregister_switchdev_notifier(&br_offloads->switchdev_nb);
> > +err_reg_switchdev_nb:
> > + destroy_workqueue(br_offloads->wq);
> > +err_alloc_wq:
> > rtnl_lock();
> > ice_eswitch_br_offloads_dealloc(pf);
> > rtnl_unlock();
> > diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h
> > index 3ad28a17298f..6fcacf545b98 100644
> > --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.h
> > +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.h
> > @@ -4,6 +4,33 @@
> > #ifndef _ICE_ESWITCH_BR_H_
> > #define _ICE_ESWITCH_BR_H_
> >
> > +#include <linux/rhashtable.h>
> > +
> > +struct ice_esw_br_fdb_data {
> > + unsigned char addr[ETH_ALEN];
> > + u16 vid;
> > +};
> > +
> > +struct ice_esw_br_flow {
> > + struct ice_rule_query_data *fwd_rule;
> > +};
> > +
> > +enum {
> > + ICE_ESWITCH_BR_FDB_ADDED_BY_USER = BIT(0),
> > +};
> > +
> > +struct ice_esw_br_fdb_entry {
> > + struct ice_esw_br_fdb_data data;
> > + struct rhash_head ht_node;
> > + struct list_head list;
> > +
> > + int flags;
> > +
> > + struct net_device *dev;
> > + struct ice_esw_br_port *br_port;
> > + struct ice_esw_br_flow *flow;
> > +};
> > +
> > enum ice_esw_br_port_type {
> > ICE_ESWITCH_BR_UPLINK_PORT = 0,
> > ICE_ESWITCH_BR_VF_REPR_PORT = 1,
> > @@ -20,6 +47,9 @@ struct ice_esw_br {
> > struct ice_esw_br_offloads *br_offloads;
> > struct xarray ports;
> >
> > + struct rhashtable fdb_ht;
> > + struct list_head fdb_list;
> > +
> > int ifindex;
> > };
> >
> > @@ -27,6 +57,17 @@ struct ice_esw_br_offloads {
> > struct ice_pf *pf;
> > struct ice_esw_br *bridge;
> > struct notifier_block netdev_nb;
> > + struct notifier_block switchdev_nb;
> > +
> > + struct workqueue_struct *wq;
> > +};
> > +
> > +struct ice_esw_br_fdb_work {
> > + struct work_struct work;
> > + struct switchdev_notifier_fdb_info fdb_info;
> > + struct ice_esw_br_port *br_port;
> > + struct net_device *dev;
> > + unsigned long event;
> > };
> >
> > #define ice_nb_to_br_offloads(nb, nb_name) \
> > @@ -34,6 +75,11 @@ struct ice_esw_br_offloads {
> > struct ice_esw_br_offloads, \
> > nb_name)
> >
> > +#define ice_work_to_fdb_work(w) \
> > + container_of(w, \
> > + struct ice_esw_br_fdb_work, \
> > + work)
> > +
> > void
> > ice_eswitch_br_offloads_deinit(struct ice_pf *pf);
> > int
Powered by blists - more mailing lists