1919 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */3 4#include <linux/if_bridge.h>5#include <linux/if_vlan.h>6#include <linux/kernel.h>7#include <linux/module.h>8#include <linux/notifier.h>9#include <net/netevent.h>10#include <net/switchdev.h>11 12#include "prestera.h"13#include "prestera_hw.h"14#include "prestera_switchdev.h"15 16#define PRESTERA_VID_ALL (0xffff)17 18#define PRESTERA_DEFAULT_AGEING_TIME_MS 30000019#define PRESTERA_MAX_AGEING_TIME_MS 100000000020#define PRESTERA_MIN_AGEING_TIME_MS 3200021 22struct prestera_fdb_event_work {23 struct work_struct work;24 struct switchdev_notifier_fdb_info fdb_info;25 struct net_device *dev;26 unsigned long event;27};28 29struct prestera_switchdev {30 struct prestera_switch *sw;31 struct list_head bridge_list;32 bool bridge_8021q_exists;33 struct notifier_block swdev_nb_blk;34 struct notifier_block swdev_nb;35};36 37struct prestera_bridge {38 struct list_head head;39 struct net_device *dev;40 struct prestera_switchdev *swdev;41 struct list_head port_list;42 struct list_head br_mdb_entry_list;43 bool mrouter_exist;44 bool vlan_enabled;45 bool multicast_enabled;46 u16 bridge_id;47};48 49struct prestera_bridge_port {50 struct list_head head;51 struct net_device *dev;52 struct prestera_bridge *bridge;53 struct list_head vlan_list;54 struct list_head br_mdb_port_list;55 refcount_t ref_count;56 unsigned long flags;57 bool mrouter;58 u8 stp_state;59};60 61struct prestera_bridge_vlan {62 struct list_head head;63 struct list_head port_vlan_list;64 u16 vid;65};66 67struct prestera_port_vlan {68 struct list_head br_vlan_head;69 struct list_head port_head;70 struct prestera_port *port;71 struct prestera_bridge_port *br_port;72 u16 vid;73};74 75struct prestera_br_mdb_port {76 struct prestera_bridge_port *br_port;77 struct list_head br_mdb_port_node;78};79 80/* Software representation of MDB table. */81struct prestera_br_mdb_entry {82 struct prestera_bridge *bridge;83 struct prestera_mdb_entry *mdb;84 struct list_head br_mdb_port_list;85 struct list_head br_mdb_entry_node;86 bool enabled;87};88 89static struct workqueue_struct *swdev_wq;90 91static void prestera_bridge_port_put(struct prestera_bridge_port *br_port);92 93static int prestera_port_vid_stp_set(struct prestera_port *port, u16 vid,94 u8 state);95 96static struct prestera_bridge *97prestera_bridge_find(const struct prestera_switch *sw,98 const struct net_device *br_dev)99{100 struct prestera_bridge *bridge;101 102 list_for_each_entry(bridge, &sw->swdev->bridge_list, head)103 if (bridge->dev == br_dev)104 return bridge;105 106 return NULL;107}108 109static struct prestera_bridge_port *110__prestera_bridge_port_find(const struct prestera_bridge *bridge,111 const struct net_device *brport_dev)112{113 struct prestera_bridge_port *br_port;114 115 list_for_each_entry(br_port, &bridge->port_list, head)116 if (br_port->dev == brport_dev)117 return br_port;118 119 return NULL;120}121 122static struct prestera_bridge_port *123prestera_bridge_port_find(struct prestera_switch *sw,124 struct net_device *brport_dev)125{126 struct net_device *br_dev = netdev_master_upper_dev_get(brport_dev);127 struct prestera_bridge *bridge;128 129 if (!br_dev)130 return NULL;131 132 bridge = prestera_bridge_find(sw, br_dev);133 if (!bridge)134 return NULL;135 136 return __prestera_bridge_port_find(bridge, brport_dev);137}138 139static void140prestera_br_port_flags_reset(struct prestera_bridge_port *br_port,141 struct prestera_port *port)142{143 prestera_port_uc_flood_set(port, false);144 prestera_port_mc_flood_set(port, false);145 prestera_port_learning_set(port, false);146 prestera_port_br_locked_set(port, false);147}148 149static int prestera_br_port_flags_set(struct prestera_bridge_port *br_port,150 struct prestera_port *port)151{152 int err;153 154 err = prestera_port_uc_flood_set(port, br_port->flags & BR_FLOOD);155 if (err)156 goto err_out;157 158 err = prestera_port_mc_flood_set(port, br_port->flags & BR_MCAST_FLOOD);159 if (err)160 goto err_out;161 162 err = prestera_port_learning_set(port, br_port->flags & BR_LEARNING);163 if (err)164 goto err_out;165 166 err = prestera_port_br_locked_set(port,167 br_port->flags & BR_PORT_LOCKED);168 if (err)169 goto err_out;170 171 return 0;172 173err_out:174 prestera_br_port_flags_reset(br_port, port);175 return err;176}177 178static struct prestera_bridge_vlan *179prestera_bridge_vlan_create(struct prestera_bridge_port *br_port, u16 vid)180{181 struct prestera_bridge_vlan *br_vlan;182 183 br_vlan = kzalloc(sizeof(*br_vlan), GFP_KERNEL);184 if (!br_vlan)185 return NULL;186 187 INIT_LIST_HEAD(&br_vlan->port_vlan_list);188 br_vlan->vid = vid;189 list_add(&br_vlan->head, &br_port->vlan_list);190 191 return br_vlan;192}193 194static void prestera_bridge_vlan_destroy(struct prestera_bridge_vlan *br_vlan)195{196 list_del(&br_vlan->head);197 WARN_ON(!list_empty(&br_vlan->port_vlan_list));198 kfree(br_vlan);199}200 201static struct prestera_bridge_vlan *202prestera_bridge_vlan_by_vid(struct prestera_bridge_port *br_port, u16 vid)203{204 struct prestera_bridge_vlan *br_vlan;205 206 list_for_each_entry(br_vlan, &br_port->vlan_list, head) {207 if (br_vlan->vid == vid)208 return br_vlan;209 }210 211 return NULL;212}213 214static int prestera_bridge_vlan_port_count(struct prestera_bridge *bridge,215 u16 vid)216{217 struct prestera_bridge_port *br_port;218 struct prestera_bridge_vlan *br_vlan;219 int count = 0;220 221 list_for_each_entry(br_port, &bridge->port_list, head) {222 list_for_each_entry(br_vlan, &br_port->vlan_list, head) {223 if (br_vlan->vid == vid) {224 count += 1;225 break;226 }227 }228 }229 230 return count;231}232 233static void prestera_bridge_vlan_put(struct prestera_bridge_vlan *br_vlan)234{235 if (list_empty(&br_vlan->port_vlan_list))236 prestera_bridge_vlan_destroy(br_vlan);237}238 239static struct prestera_port_vlan *240prestera_port_vlan_by_vid(struct prestera_port *port, u16 vid)241{242 struct prestera_port_vlan *port_vlan;243 244 list_for_each_entry(port_vlan, &port->vlans_list, port_head) {245 if (port_vlan->vid == vid)246 return port_vlan;247 }248 249 return NULL;250}251 252static struct prestera_port_vlan *253prestera_port_vlan_create(struct prestera_port *port, u16 vid, bool untagged)254{255 struct prestera_port_vlan *port_vlan;256 int err;257 258 port_vlan = prestera_port_vlan_by_vid(port, vid);259 if (port_vlan)260 return ERR_PTR(-EEXIST);261 262 err = prestera_hw_vlan_port_set(port, vid, true, untagged);263 if (err)264 return ERR_PTR(err);265 266 port_vlan = kzalloc(sizeof(*port_vlan), GFP_KERNEL);267 if (!port_vlan) {268 err = -ENOMEM;269 goto err_port_vlan_alloc;270 }271 272 port_vlan->port = port;273 port_vlan->vid = vid;274 275 list_add(&port_vlan->port_head, &port->vlans_list);276 277 return port_vlan;278 279err_port_vlan_alloc:280 prestera_hw_vlan_port_set(port, vid, false, false);281 return ERR_PTR(err);282}283 284static int prestera_fdb_add(struct prestera_port *port,285 const unsigned char *mac, u16 vid, bool dynamic)286{287 if (prestera_port_is_lag_member(port))288 return prestera_hw_lag_fdb_add(port->sw, prestera_port_lag_id(port),289 mac, vid, dynamic);290 291 return prestera_hw_fdb_add(port, mac, vid, dynamic);292}293 294static int prestera_fdb_del(struct prestera_port *port,295 const unsigned char *mac, u16 vid)296{297 if (prestera_port_is_lag_member(port))298 return prestera_hw_lag_fdb_del(port->sw, prestera_port_lag_id(port),299 mac, vid);300 else301 return prestera_hw_fdb_del(port, mac, vid);302}303 304static int prestera_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,305 u32 mode)306{307 if (prestera_port_is_lag_member(port))308 return prestera_hw_fdb_flush_lag_vlan(port->sw, prestera_port_lag_id(port),309 vid, mode);310 else311 return prestera_hw_fdb_flush_port_vlan(port, vid, mode);312}313 314static int prestera_fdb_flush_port(struct prestera_port *port, u32 mode)315{316 if (prestera_port_is_lag_member(port))317 return prestera_hw_fdb_flush_lag(port->sw, prestera_port_lag_id(port),318 mode);319 else320 return prestera_hw_fdb_flush_port(port, mode);321}322 323static void324prestera_mdb_port_del(struct prestera_mdb_entry *mdb,325 struct net_device *orig_dev)326{327 struct prestera_flood_domain *fl_domain = mdb->flood_domain;328 struct prestera_flood_domain_port *flood_domain_port;329 330 flood_domain_port = prestera_flood_domain_port_find(fl_domain,331 orig_dev,332 mdb->vid);333 if (flood_domain_port)334 prestera_flood_domain_port_destroy(flood_domain_port);335}336 337static void338prestera_br_mdb_entry_put(struct prestera_br_mdb_entry *br_mdb)339{340 struct prestera_bridge_port *br_port;341 342 if (list_empty(&br_mdb->br_mdb_port_list)) {343 list_for_each_entry(br_port, &br_mdb->bridge->port_list, head)344 prestera_mdb_port_del(br_mdb->mdb, br_port->dev);345 346 prestera_mdb_entry_destroy(br_mdb->mdb);347 list_del(&br_mdb->br_mdb_entry_node);348 kfree(br_mdb);349 }350}351 352static void353prestera_br_mdb_port_del(struct prestera_br_mdb_entry *br_mdb,354 struct prestera_bridge_port *br_port)355{356 struct prestera_br_mdb_port *br_mdb_port, *tmp;357 358 list_for_each_entry_safe(br_mdb_port, tmp, &br_mdb->br_mdb_port_list,359 br_mdb_port_node) {360 if (br_mdb_port->br_port == br_port) {361 list_del(&br_mdb_port->br_mdb_port_node);362 kfree(br_mdb_port);363 }364 }365}366 367static void368prestera_mdb_flush_bridge_port(struct prestera_bridge_port *br_port)369{370 struct prestera_br_mdb_port *br_mdb_port, *tmp_port;371 struct prestera_br_mdb_entry *br_mdb, *br_mdb_tmp;372 struct prestera_bridge *br_dev = br_port->bridge;373 374 list_for_each_entry_safe(br_mdb, br_mdb_tmp, &br_dev->br_mdb_entry_list,375 br_mdb_entry_node) {376 list_for_each_entry_safe(br_mdb_port, tmp_port,377 &br_mdb->br_mdb_port_list,378 br_mdb_port_node) {379 prestera_mdb_port_del(br_mdb->mdb,380 br_mdb_port->br_port->dev);381 prestera_br_mdb_port_del(br_mdb, br_mdb_port->br_port);382 }383 prestera_br_mdb_entry_put(br_mdb);384 }385}386 387static void388prestera_port_vlan_bridge_leave(struct prestera_port_vlan *port_vlan)389{390 u32 fdb_flush_mode = PRESTERA_FDB_FLUSH_MODE_DYNAMIC;391 struct prestera_port *port = port_vlan->port;392 struct prestera_bridge_vlan *br_vlan;393 struct prestera_bridge_port *br_port;394 bool last_port, last_vlan;395 u16 vid = port_vlan->vid;396 int port_count;397 398 br_port = port_vlan->br_port;399 port_count = prestera_bridge_vlan_port_count(br_port->bridge, vid);400 br_vlan = prestera_bridge_vlan_by_vid(br_port, vid);401 402 last_vlan = list_is_singular(&br_port->vlan_list);403 last_port = port_count == 1;404 405 if (last_vlan)406 prestera_fdb_flush_port(port, fdb_flush_mode);407 else if (last_port)408 prestera_hw_fdb_flush_vlan(port->sw, vid, fdb_flush_mode);409 else410 prestera_fdb_flush_port_vlan(port, vid, fdb_flush_mode);411 412 prestera_mdb_flush_bridge_port(br_port);413 414 list_del(&port_vlan->br_vlan_head);415 prestera_bridge_vlan_put(br_vlan);416 prestera_bridge_port_put(br_port);417 port_vlan->br_port = NULL;418}419 420static void prestera_port_vlan_destroy(struct prestera_port_vlan *port_vlan)421{422 struct prestera_port *port = port_vlan->port;423 u16 vid = port_vlan->vid;424 425 if (port_vlan->br_port)426 prestera_port_vlan_bridge_leave(port_vlan);427 428 prestera_hw_vlan_port_set(port, vid, false, false);429 list_del(&port_vlan->port_head);430 kfree(port_vlan);431}432 433static struct prestera_bridge *434prestera_bridge_create(struct prestera_switchdev *swdev, struct net_device *dev)435{436 bool vlan_enabled = br_vlan_enabled(dev);437 struct prestera_bridge *bridge;438 u16 bridge_id;439 int err;440 441 if (vlan_enabled && swdev->bridge_8021q_exists) {442 netdev_err(dev, "Only one VLAN-aware bridge is supported\n");443 return ERR_PTR(-EINVAL);444 }445 446 bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);447 if (!bridge)448 return ERR_PTR(-ENOMEM);449 450 if (vlan_enabled) {451 swdev->bridge_8021q_exists = true;452 } else {453 err = prestera_hw_bridge_create(swdev->sw, &bridge_id);454 if (err) {455 kfree(bridge);456 return ERR_PTR(err);457 }458 459 bridge->bridge_id = bridge_id;460 }461 462 bridge->vlan_enabled = vlan_enabled;463 bridge->swdev = swdev;464 bridge->dev = dev;465 bridge->multicast_enabled = br_multicast_enabled(dev);466 467 INIT_LIST_HEAD(&bridge->port_list);468 INIT_LIST_HEAD(&bridge->br_mdb_entry_list);469 470 list_add(&bridge->head, &swdev->bridge_list);471 472 return bridge;473}474 475static void prestera_bridge_destroy(struct prestera_bridge *bridge)476{477 struct prestera_switchdev *swdev = bridge->swdev;478 479 list_del(&bridge->head);480 481 if (bridge->vlan_enabled)482 swdev->bridge_8021q_exists = false;483 else484 prestera_hw_bridge_delete(swdev->sw, bridge->bridge_id);485 486 WARN_ON(!list_empty(&bridge->br_mdb_entry_list));487 WARN_ON(!list_empty(&bridge->port_list));488 kfree(bridge);489}490 491static void prestera_bridge_put(struct prestera_bridge *bridge)492{493 if (list_empty(&bridge->port_list))494 prestera_bridge_destroy(bridge);495}496 497static498struct prestera_bridge *prestera_bridge_by_dev(struct prestera_switchdev *swdev,499 const struct net_device *dev)500{501 struct prestera_bridge *bridge;502 503 list_for_each_entry(bridge, &swdev->bridge_list, head)504 if (bridge->dev == dev)505 return bridge;506 507 return NULL;508}509 510static struct prestera_bridge_port *511__prestera_bridge_port_by_dev(struct prestera_bridge *bridge,512 struct net_device *dev)513{514 struct prestera_bridge_port *br_port;515 516 list_for_each_entry(br_port, &bridge->port_list, head) {517 if (br_port->dev == dev)518 return br_port;519 }520 521 return NULL;522}523 524static int prestera_match_upper_bridge_dev(struct net_device *dev,525 struct netdev_nested_priv *priv)526{527 if (netif_is_bridge_master(dev))528 priv->data = dev;529 530 return 0;531}532 533static struct net_device *prestera_get_upper_bridge_dev(struct net_device *dev)534{535 struct netdev_nested_priv priv = { };536 537 netdev_walk_all_upper_dev_rcu(dev, prestera_match_upper_bridge_dev,538 &priv);539 return priv.data;540}541 542static struct prestera_bridge_port *543prestera_bridge_port_by_dev(struct prestera_switchdev *swdev,544 struct net_device *dev)545{546 struct net_device *br_dev = prestera_get_upper_bridge_dev(dev);547 struct prestera_bridge *bridge;548 549 if (!br_dev)550 return NULL;551 552 bridge = prestera_bridge_by_dev(swdev, br_dev);553 if (!bridge)554 return NULL;555 556 return __prestera_bridge_port_by_dev(bridge, dev);557}558 559static struct prestera_bridge_port *560prestera_bridge_port_create(struct prestera_bridge *bridge,561 struct net_device *dev)562{563 struct prestera_bridge_port *br_port;564 565 br_port = kzalloc(sizeof(*br_port), GFP_KERNEL);566 if (!br_port)567 return NULL;568 569 br_port->flags = BR_LEARNING | BR_FLOOD | BR_LEARNING_SYNC |570 BR_MCAST_FLOOD;571 br_port->stp_state = BR_STATE_DISABLED;572 refcount_set(&br_port->ref_count, 1);573 br_port->bridge = bridge;574 br_port->dev = dev;575 576 INIT_LIST_HEAD(&br_port->vlan_list);577 list_add(&br_port->head, &bridge->port_list);578 INIT_LIST_HEAD(&br_port->br_mdb_port_list);579 580 return br_port;581}582 583static void584prestera_bridge_port_destroy(struct prestera_bridge_port *br_port)585{586 list_del(&br_port->head);587 WARN_ON(!list_empty(&br_port->vlan_list));588 WARN_ON(!list_empty(&br_port->br_mdb_port_list));589 kfree(br_port);590}591 592static void prestera_bridge_port_get(struct prestera_bridge_port *br_port)593{594 refcount_inc(&br_port->ref_count);595}596 597static void prestera_bridge_port_put(struct prestera_bridge_port *br_port)598{599 struct prestera_bridge *bridge = br_port->bridge;600 601 if (refcount_dec_and_test(&br_port->ref_count)) {602 prestera_bridge_port_destroy(br_port);603 prestera_bridge_put(bridge);604 }605}606 607static struct prestera_bridge_port *608prestera_bridge_port_add(struct prestera_bridge *bridge, struct net_device *dev)609{610 struct prestera_bridge_port *br_port;611 612 br_port = __prestera_bridge_port_by_dev(bridge, dev);613 if (br_port) {614 prestera_bridge_port_get(br_port);615 return br_port;616 }617 618 br_port = prestera_bridge_port_create(bridge, dev);619 if (!br_port)620 return ERR_PTR(-ENOMEM);621 622 return br_port;623}624 625static int626prestera_bridge_1d_port_join(struct prestera_bridge_port *br_port)627{628 struct prestera_port *port = netdev_priv(br_port->dev);629 struct prestera_bridge *bridge = br_port->bridge;630 int err;631 632 err = prestera_hw_bridge_port_add(port, bridge->bridge_id);633 if (err)634 return err;635 636 err = prestera_br_port_flags_set(br_port, port);637 if (err)638 goto err_flags2port_set;639 640 return 0;641 642err_flags2port_set:643 prestera_hw_bridge_port_delete(port, bridge->bridge_id);644 645 return err;646}647 648int prestera_bridge_port_join(struct net_device *br_dev,649 struct prestera_port *port,650 struct netlink_ext_ack *extack)651{652 struct prestera_switchdev *swdev = port->sw->swdev;653 struct prestera_bridge_port *br_port;654 struct prestera_bridge *bridge;655 int err;656 657 bridge = prestera_bridge_by_dev(swdev, br_dev);658 if (!bridge) {659 bridge = prestera_bridge_create(swdev, br_dev);660 if (IS_ERR(bridge))661 return PTR_ERR(bridge);662 }663 664 br_port = prestera_bridge_port_add(bridge, port->dev);665 if (IS_ERR(br_port)) {666 prestera_bridge_put(bridge);667 return PTR_ERR(br_port);668 }669 670 err = switchdev_bridge_port_offload(br_port->dev, port->dev, NULL,671 NULL, NULL, false, extack);672 if (err)673 goto err_switchdev_offload;674 675 if (bridge->vlan_enabled)676 return 0;677 678 err = prestera_bridge_1d_port_join(br_port);679 if (err)680 goto err_port_join;681 682 return 0;683 684err_port_join:685 switchdev_bridge_port_unoffload(br_port->dev, NULL, NULL, NULL);686err_switchdev_offload:687 prestera_bridge_port_put(br_port);688 return err;689}690 691static void prestera_bridge_1q_port_leave(struct prestera_bridge_port *br_port)692{693 struct prestera_port *port = netdev_priv(br_port->dev);694 695 prestera_hw_fdb_flush_port(port, PRESTERA_FDB_FLUSH_MODE_ALL);696 prestera_port_pvid_set(port, PRESTERA_DEFAULT_VID);697}698 699static void prestera_bridge_1d_port_leave(struct prestera_bridge_port *br_port)700{701 struct prestera_port *port = netdev_priv(br_port->dev);702 703 prestera_hw_fdb_flush_port(port, PRESTERA_FDB_FLUSH_MODE_ALL);704 prestera_hw_bridge_port_delete(port, br_port->bridge->bridge_id);705}706 707static int prestera_port_vid_stp_set(struct prestera_port *port, u16 vid,708 u8 state)709{710 u8 hw_state = state;711 712 switch (state) {713 case BR_STATE_DISABLED:714 hw_state = PRESTERA_STP_DISABLED;715 break;716 717 case BR_STATE_BLOCKING:718 case BR_STATE_LISTENING:719 hw_state = PRESTERA_STP_BLOCK_LISTEN;720 break;721 722 case BR_STATE_LEARNING:723 hw_state = PRESTERA_STP_LEARN;724 break;725 726 case BR_STATE_FORWARDING:727 hw_state = PRESTERA_STP_FORWARD;728 break;729 730 default:731 return -EINVAL;732 }733 734 return prestera_hw_vlan_port_stp_set(port, vid, hw_state);735}736 737void prestera_bridge_port_leave(struct net_device *br_dev,738 struct prestera_port *port)739{740 struct prestera_switchdev *swdev = port->sw->swdev;741 struct prestera_bridge_port *br_port;742 struct prestera_bridge *bridge;743 744 bridge = prestera_bridge_by_dev(swdev, br_dev);745 if (!bridge)746 return;747 748 br_port = __prestera_bridge_port_by_dev(bridge, port->dev);749 if (!br_port)750 return;751 752 bridge = br_port->bridge;753 754 if (bridge->vlan_enabled)755 prestera_bridge_1q_port_leave(br_port);756 else757 prestera_bridge_1d_port_leave(br_port);758 759 switchdev_bridge_port_unoffload(br_port->dev, NULL, NULL, NULL);760 761 prestera_mdb_flush_bridge_port(br_port);762 763 prestera_br_port_flags_reset(br_port, port);764 prestera_port_vid_stp_set(port, PRESTERA_VID_ALL, BR_STATE_FORWARDING);765 prestera_bridge_port_put(br_port);766}767 768static int prestera_port_attr_br_flags_set(struct prestera_port *port,769 struct net_device *dev,770 struct switchdev_brport_flags flags)771{772 struct prestera_bridge_port *br_port;773 774 br_port = prestera_bridge_port_by_dev(port->sw->swdev, dev);775 if (!br_port)776 return 0;777 778 br_port->flags &= ~flags.mask;779 br_port->flags |= flags.val & flags.mask;780 return prestera_br_port_flags_set(br_port, port);781}782 783static int prestera_port_attr_br_ageing_set(struct prestera_port *port,784 unsigned long ageing_clock_t)785{786 unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t);787 u32 ageing_time_ms = jiffies_to_msecs(ageing_jiffies);788 struct prestera_switch *sw = port->sw;789 790 if (ageing_time_ms < PRESTERA_MIN_AGEING_TIME_MS ||791 ageing_time_ms > PRESTERA_MAX_AGEING_TIME_MS)792 return -ERANGE;793 794 return prestera_hw_switch_ageing_set(sw, ageing_time_ms);795}796 797static int prestera_port_attr_br_vlan_set(struct prestera_port *port,798 struct net_device *dev,799 bool vlan_enabled)800{801 struct prestera_switch *sw = port->sw;802 struct prestera_bridge *bridge;803 804 bridge = prestera_bridge_by_dev(sw->swdev, dev);805 if (WARN_ON(!bridge))806 return -EINVAL;807 808 if (bridge->vlan_enabled == vlan_enabled)809 return 0;810 811 netdev_err(bridge->dev, "VLAN filtering can't be changed for existing bridge\n");812 813 return -EINVAL;814}815 816static int prestera_port_bridge_vlan_stp_set(struct prestera_port *port,817 struct prestera_bridge_vlan *br_vlan,818 u8 state)819{820 struct prestera_port_vlan *port_vlan;821 822 list_for_each_entry(port_vlan, &br_vlan->port_vlan_list, br_vlan_head) {823 if (port_vlan->port != port)824 continue;825 826 return prestera_port_vid_stp_set(port, br_vlan->vid, state);827 }828 829 return 0;830}831 832static int prestera_port_attr_stp_state_set(struct prestera_port *port,833 struct net_device *dev,834 u8 state)835{836 struct prestera_bridge_port *br_port;837 struct prestera_bridge_vlan *br_vlan;838 int err;839 u16 vid;840 841 br_port = prestera_bridge_port_by_dev(port->sw->swdev, dev);842 if (!br_port)843 return 0;844 845 if (!br_port->bridge->vlan_enabled) {846 vid = br_port->bridge->bridge_id;847 err = prestera_port_vid_stp_set(port, vid, state);848 if (err)849 goto err_port_stp_set;850 } else {851 list_for_each_entry(br_vlan, &br_port->vlan_list, head) {852 err = prestera_port_bridge_vlan_stp_set(port, br_vlan,853 state);854 if (err)855 goto err_port_vlan_stp_set;856 }857 }858 859 br_port->stp_state = state;860 861 return 0;862 863err_port_vlan_stp_set:864 list_for_each_entry_continue_reverse(br_vlan, &br_port->vlan_list, head)865 prestera_port_bridge_vlan_stp_set(port, br_vlan, br_port->stp_state);866 return err;867 868err_port_stp_set:869 prestera_port_vid_stp_set(port, vid, br_port->stp_state);870 871 return err;872}873 874static int875prestera_br_port_lag_mdb_mc_enable_sync(struct prestera_bridge_port *br_port,876 bool enabled)877{878 struct prestera_port *pr_port;879 struct prestera_switch *sw;880 u16 lag_id;881 int err;882 883 pr_port = prestera_port_dev_lower_find(br_port->dev);884 if (!pr_port)885 return 0;886 887 sw = pr_port->sw;888 err = prestera_lag_id(sw, br_port->dev, &lag_id);889 if (err)890 return err;891 892 list_for_each_entry(pr_port, &sw->port_list, list) {893 if (pr_port->lag->lag_id == lag_id) {894 err = prestera_port_mc_flood_set(pr_port, enabled);895 if (err)896 return err;897 }898 }899 900 return 0;901}902 903static int prestera_br_mdb_mc_enable_sync(struct prestera_bridge *br_dev)904{905 struct prestera_bridge_port *br_port;906 struct prestera_port *port;907 bool enabled;908 int err;909 910 /* if mrouter exists:911 * - make sure every mrouter receives unreg mcast traffic;912 * if mrouter doesn't exists:913 * - make sure every port receives unreg mcast traffic;914 */915 list_for_each_entry(br_port, &br_dev->port_list, head) {916 if (br_dev->multicast_enabled && br_dev->mrouter_exist)917 enabled = br_port->mrouter;918 else919 enabled = br_port->flags & BR_MCAST_FLOOD;920 921 if (netif_is_lag_master(br_port->dev)) {922 err = prestera_br_port_lag_mdb_mc_enable_sync(br_port,923 enabled);924 if (err)925 return err;926 continue;927 }928 929 port = prestera_port_dev_lower_find(br_port->dev);930 if (!port)931 continue;932 933 err = prestera_port_mc_flood_set(port, enabled);934 if (err)935 return err;936 }937 938 return 0;939}940 941static bool942prestera_br_mdb_port_is_member(struct prestera_br_mdb_entry *br_mdb,943 struct net_device *orig_dev)944{945 struct prestera_br_mdb_port *tmp_port;946 947 list_for_each_entry(tmp_port, &br_mdb->br_mdb_port_list,948 br_mdb_port_node)949 if (tmp_port->br_port->dev == orig_dev)950 return true;951 952 return false;953}954 955static int956prestera_mdb_port_add(struct prestera_mdb_entry *mdb,957 struct net_device *orig_dev,958 const unsigned char addr[ETH_ALEN], u16 vid)959{960 struct prestera_flood_domain *flood_domain = mdb->flood_domain;961 int err;962 963 if (!prestera_flood_domain_port_find(flood_domain,964 orig_dev, vid)) {965 err = prestera_flood_domain_port_create(flood_domain, orig_dev,966 vid);967 if (err)968 return err;969 }970 971 return 0;972}973 974/* Sync bridge mdb (software table) with HW table (if MC is enabled). */975static int prestera_br_mdb_sync(struct prestera_bridge *br_dev)976{977 struct prestera_br_mdb_port *br_mdb_port;978 struct prestera_bridge_port *br_port;979 struct prestera_br_mdb_entry *br_mdb;980 struct prestera_mdb_entry *mdb;981 struct prestera_port *pr_port;982 int err = 0;983 984 if (!br_dev->multicast_enabled)985 return 0;986 987 list_for_each_entry(br_mdb, &br_dev->br_mdb_entry_list,988 br_mdb_entry_node) {989 mdb = br_mdb->mdb;990 /* Make sure every port that explicitly been added to the mdb991 * joins the specified group.992 */993 list_for_each_entry(br_mdb_port, &br_mdb->br_mdb_port_list,994 br_mdb_port_node) {995 br_port = br_mdb_port->br_port;996 pr_port = prestera_port_dev_lower_find(br_port->dev);997 998 /* Match only mdb and br_mdb ports that belong to the999 * same broadcast domain.1000 */1001 if (br_dev->vlan_enabled &&1002 !prestera_port_vlan_by_vid(pr_port,1003 mdb->vid))1004 continue;1005 1006 /* If port is not in MDB or there's no Mrouter1007 * clear HW mdb.1008 */1009 if (prestera_br_mdb_port_is_member(br_mdb,1010 br_mdb_port->br_port->dev) &&1011 br_dev->mrouter_exist)1012 err = prestera_mdb_port_add(mdb, br_port->dev,1013 mdb->addr,1014 mdb->vid);1015 else1016 prestera_mdb_port_del(mdb, br_port->dev);1017 1018 if (err)1019 return err;1020 }1021 1022 /* Make sure that every mrouter port joins every MC group int1023 * broadcast domain. If it's not an mrouter - it should leave1024 */1025 list_for_each_entry(br_port, &br_dev->port_list, head) {1026 pr_port = prestera_port_dev_lower_find(br_port->dev);1027 1028 /* Make sure mrouter woudln't receive traffci from1029 * another broadcast domain (e.g. from a vlan, which1030 * mrouter port is not a member of).1031 */1032 if (br_dev->vlan_enabled &&1033 !prestera_port_vlan_by_vid(pr_port,1034 mdb->vid))1035 continue;1036 1037 if (br_port->mrouter) {1038 err = prestera_mdb_port_add(mdb, br_port->dev,1039 mdb->addr,1040 mdb->vid);1041 if (err)1042 return err;1043 } else if (!br_port->mrouter &&1044 !prestera_br_mdb_port_is_member1045 (br_mdb, br_port->dev)) {1046 prestera_mdb_port_del(mdb, br_port->dev);1047 }1048 }1049 }1050 1051 return 0;1052}1053 1054static int1055prestera_mdb_enable_set(struct prestera_br_mdb_entry *br_mdb, bool enable)1056{1057 int err;1058 1059 if (enable != br_mdb->enabled) {1060 if (enable)1061 err = prestera_hw_mdb_create(br_mdb->mdb);1062 else1063 err = prestera_hw_mdb_destroy(br_mdb->mdb);1064 1065 if (err)1066 return err;1067 1068 br_mdb->enabled = enable;1069 }1070 1071 return 0;1072}1073 1074static int1075prestera_br_mdb_enable_set(struct prestera_bridge *br_dev, bool enable)1076{1077 struct prestera_br_mdb_entry *br_mdb;1078 int err;1079 1080 list_for_each_entry(br_mdb, &br_dev->br_mdb_entry_list,1081 br_mdb_entry_node) {1082 err = prestera_mdb_enable_set(br_mdb, enable);1083 if (err)1084 return err;1085 }1086 1087 return 0;1088}1089 1090static int prestera_port_attr_br_mc_disabled_set(struct prestera_port *port,1091 struct net_device *orig_dev,1092 bool mc_disabled)1093{1094 struct prestera_switch *sw = port->sw;1095 struct prestera_bridge *br_dev;1096 1097 br_dev = prestera_bridge_find(sw, orig_dev);1098 if (!br_dev)1099 return 0;1100 1101 br_dev->multicast_enabled = !mc_disabled;1102 1103 /* There's no point in enabling mdb back if router is missing. */1104 WARN_ON(prestera_br_mdb_enable_set(br_dev, br_dev->multicast_enabled &&1105 br_dev->mrouter_exist));1106 1107 WARN_ON(prestera_br_mdb_sync(br_dev));1108 1109 WARN_ON(prestera_br_mdb_mc_enable_sync(br_dev));1110 1111 return 0;1112}1113 1114static bool1115prestera_bridge_mdb_mc_mrouter_exists(struct prestera_bridge *br_dev)1116{1117 struct prestera_bridge_port *br_port;1118 1119 list_for_each_entry(br_port, &br_dev->port_list, head)1120 if (br_port->mrouter)1121 return true;1122 1123 return false;1124}1125 1126static int1127prestera_port_attr_mrouter_set(struct prestera_port *port,1128 struct net_device *orig_dev,1129 bool is_port_mrouter)1130{1131 struct prestera_bridge_port *br_port;1132 struct prestera_bridge *br_dev;1133 1134 br_port = prestera_bridge_port_find(port->sw, orig_dev);1135 if (!br_port)1136 return 0;1137 1138 br_dev = br_port->bridge;1139 br_port->mrouter = is_port_mrouter;1140 1141 br_dev->mrouter_exist = prestera_bridge_mdb_mc_mrouter_exists(br_dev);1142 1143 /* Enable MDB processing if both mrouter exists and mc is enabled.1144 * In case if MC enabled, but there is no mrouter, device would flood1145 * all multicast traffic (even if MDB table is not empty) with the use1146 * of bridge's flood capabilities (without the use of flood_domain).1147 */1148 WARN_ON(prestera_br_mdb_enable_set(br_dev, br_dev->multicast_enabled &&1149 br_dev->mrouter_exist));1150 1151 WARN_ON(prestera_br_mdb_sync(br_dev));1152 1153 WARN_ON(prestera_br_mdb_mc_enable_sync(br_dev));1154 1155 return 0;1156}1157 1158static int prestera_port_obj_attr_set(struct net_device *dev, const void *ctx,1159 const struct switchdev_attr *attr,1160 struct netlink_ext_ack *extack)1161{1162 struct prestera_port *port = netdev_priv(dev);1163 int err = 0;1164 1165 switch (attr->id) {1166 case SWITCHDEV_ATTR_ID_PORT_STP_STATE:1167 err = prestera_port_attr_stp_state_set(port, attr->orig_dev,1168 attr->u.stp_state);1169 break;1170 case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:1171 if (attr->u.brport_flags.mask &1172 ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_PORT_LOCKED))1173 err = -EINVAL;1174 break;1175 case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:1176 err = prestera_port_attr_br_flags_set(port, attr->orig_dev,1177 attr->u.brport_flags);1178 break;1179 case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:1180 err = prestera_port_attr_br_ageing_set(port,1181 attr->u.ageing_time);1182 break;1183 case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:1184 err = prestera_port_attr_br_vlan_set(port, attr->orig_dev,1185 attr->u.vlan_filtering);1186 break;1187 case SWITCHDEV_ATTR_ID_PORT_MROUTER:1188 err = prestera_port_attr_mrouter_set(port, attr->orig_dev,1189 attr->u.mrouter);1190 break;1191 case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:1192 err = prestera_port_attr_br_mc_disabled_set(port, attr->orig_dev,1193 attr->u.mc_disabled);1194 break;1195 default:1196 err = -EOPNOTSUPP;1197 }1198 1199 return err;1200}1201 1202static void1203prestera_fdb_offload_notify(struct prestera_port *port,1204 struct switchdev_notifier_fdb_info *info)1205{1206 struct switchdev_notifier_fdb_info send_info = {};1207 1208 send_info.addr = info->addr;1209 send_info.vid = info->vid;1210 send_info.offloaded = true;1211 1212 call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, port->dev,1213 &send_info.info, NULL);1214}1215 1216static int prestera_port_fdb_set(struct prestera_port *port,1217 struct switchdev_notifier_fdb_info *fdb_info,1218 bool adding)1219{1220 struct prestera_switch *sw = port->sw;1221 struct prestera_bridge_port *br_port;1222 struct prestera_bridge *bridge;1223 int err;1224 u16 vid;1225 1226 br_port = prestera_bridge_port_by_dev(sw->swdev, port->dev);1227 if (!br_port)1228 return -EINVAL;1229 1230 bridge = br_port->bridge;1231 1232 if (bridge->vlan_enabled)1233 vid = fdb_info->vid;1234 else1235 vid = bridge->bridge_id;1236 1237 if (adding)1238 err = prestera_fdb_add(port, fdb_info->addr, vid, false);1239 else1240 err = prestera_fdb_del(port, fdb_info->addr, vid);1241 1242 return err;1243}1244 1245static void prestera_fdb_event_work(struct work_struct *work)1246{1247 struct switchdev_notifier_fdb_info *fdb_info;1248 struct prestera_fdb_event_work *swdev_work;1249 struct prestera_port *port;1250 struct net_device *dev;1251 int err;1252 1253 swdev_work = container_of(work, struct prestera_fdb_event_work, work);1254 dev = swdev_work->dev;1255 1256 rtnl_lock();1257 1258 port = prestera_port_dev_lower_find(dev);1259 if (!port)1260 goto out_unlock;1261 1262 switch (swdev_work->event) {1263 case SWITCHDEV_FDB_ADD_TO_DEVICE:1264 fdb_info = &swdev_work->fdb_info;1265 if (!fdb_info->added_by_user || fdb_info->is_local)1266 break;1267 1268 err = prestera_port_fdb_set(port, fdb_info, true);1269 if (err)1270 break;1271 1272 prestera_fdb_offload_notify(port, fdb_info);1273 break;1274 1275 case SWITCHDEV_FDB_DEL_TO_DEVICE:1276 fdb_info = &swdev_work->fdb_info;1277 prestera_port_fdb_set(port, fdb_info, false);1278 break;1279 }1280 1281out_unlock:1282 rtnl_unlock();1283 1284 kfree(swdev_work->fdb_info.addr);1285 kfree(swdev_work);1286 dev_put(dev);1287}1288 1289static int prestera_switchdev_event(struct notifier_block *unused,1290 unsigned long event, void *ptr)1291{1292 struct net_device *dev = switchdev_notifier_info_to_dev(ptr);1293 struct switchdev_notifier_fdb_info *fdb_info;1294 struct switchdev_notifier_info *info = ptr;1295 struct prestera_fdb_event_work *swdev_work;1296 struct net_device *upper;1297 int err;1298 1299 if (event == SWITCHDEV_PORT_ATTR_SET) {1300 err = switchdev_handle_port_attr_set(dev, ptr,1301 prestera_netdev_check,1302 prestera_port_obj_attr_set);1303 return notifier_from_errno(err);1304 }1305 1306 if (!prestera_netdev_check(dev))1307 return NOTIFY_DONE;1308 1309 upper = netdev_master_upper_dev_get_rcu(dev);1310 if (!upper)1311 return NOTIFY_DONE;1312 1313 if (!netif_is_bridge_master(upper))1314 return NOTIFY_DONE;1315 1316 swdev_work = kzalloc(sizeof(*swdev_work), GFP_ATOMIC);1317 if (!swdev_work)1318 return NOTIFY_BAD;1319 1320 swdev_work->event = event;1321 swdev_work->dev = dev;1322 1323 switch (event) {1324 case SWITCHDEV_FDB_ADD_TO_DEVICE:1325 case SWITCHDEV_FDB_DEL_TO_DEVICE:1326 fdb_info = container_of(info,1327 struct switchdev_notifier_fdb_info,1328 info);1329 1330 INIT_WORK(&swdev_work->work, prestera_fdb_event_work);1331 memcpy(&swdev_work->fdb_info, ptr,1332 sizeof(swdev_work->fdb_info));1333 1334 swdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);1335 if (!swdev_work->fdb_info.addr)1336 goto out_bad;1337 1338 ether_addr_copy((u8 *)swdev_work->fdb_info.addr,1339 fdb_info->addr);1340 dev_hold(dev);1341 break;1342 1343 default:1344 kfree(swdev_work);1345 return NOTIFY_DONE;1346 }1347 1348 queue_work(swdev_wq, &swdev_work->work);1349 return NOTIFY_DONE;1350 1351out_bad:1352 kfree(swdev_work);1353 return NOTIFY_BAD;1354}1355 1356static int1357prestera_port_vlan_bridge_join(struct prestera_port_vlan *port_vlan,1358 struct prestera_bridge_port *br_port)1359{1360 struct prestera_port *port = port_vlan->port;1361 struct prestera_bridge_vlan *br_vlan;1362 u16 vid = port_vlan->vid;1363 int err;1364 1365 if (port_vlan->br_port)1366 return 0;1367 1368 err = prestera_br_port_flags_set(br_port, port);1369 if (err)1370 goto err_flags2port_set;1371 1372 err = prestera_port_vid_stp_set(port, vid, br_port->stp_state);1373 if (err)1374 goto err_port_vid_stp_set;1375 1376 br_vlan = prestera_bridge_vlan_by_vid(br_port, vid);1377 if (!br_vlan) {1378 br_vlan = prestera_bridge_vlan_create(br_port, vid);1379 if (!br_vlan) {1380 err = -ENOMEM;1381 goto err_bridge_vlan_get;1382 }1383 }1384 1385 list_add(&port_vlan->br_vlan_head, &br_vlan->port_vlan_list);1386 1387 prestera_bridge_port_get(br_port);1388 port_vlan->br_port = br_port;1389 1390 return 0;1391 1392err_bridge_vlan_get:1393 prestera_port_vid_stp_set(port, vid, BR_STATE_FORWARDING);1394err_port_vid_stp_set:1395 prestera_br_port_flags_reset(br_port, port);1396err_flags2port_set:1397 return err;1398}1399 1400static int1401prestera_bridge_port_vlan_add(struct prestera_port *port,1402 struct prestera_bridge_port *br_port,1403 u16 vid, bool is_untagged, bool is_pvid,1404 struct netlink_ext_ack *extack)1405{1406 struct prestera_port_vlan *port_vlan;1407 u16 old_pvid = port->pvid;1408 u16 pvid;1409 int err;1410 1411 if (is_pvid)1412 pvid = vid;1413 else1414 pvid = port->pvid == vid ? 0 : port->pvid;1415 1416 port_vlan = prestera_port_vlan_by_vid(port, vid);1417 if (port_vlan && port_vlan->br_port != br_port)1418 return -EEXIST;1419 1420 if (!port_vlan) {1421 port_vlan = prestera_port_vlan_create(port, vid, is_untagged);1422 if (IS_ERR(port_vlan))1423 return PTR_ERR(port_vlan);1424 } else {1425 err = prestera_hw_vlan_port_set(port, vid, true, is_untagged);1426 if (err)1427 goto err_port_vlan_set;1428 }1429 1430 err = prestera_port_pvid_set(port, pvid);1431 if (err)1432 goto err_port_pvid_set;1433 1434 err = prestera_port_vlan_bridge_join(port_vlan, br_port);1435 if (err)1436 goto err_port_vlan_bridge_join;1437 1438 return 0;1439 1440err_port_vlan_bridge_join:1441 prestera_port_pvid_set(port, old_pvid);1442err_port_pvid_set:1443 prestera_hw_vlan_port_set(port, vid, false, false);1444err_port_vlan_set:1445 prestera_port_vlan_destroy(port_vlan);1446 1447 return err;1448}1449 1450static void1451prestera_bridge_port_vlan_del(struct prestera_port *port,1452 struct prestera_bridge_port *br_port, u16 vid)1453{1454 u16 pvid = port->pvid == vid ? 0 : port->pvid;1455 struct prestera_port_vlan *port_vlan;1456 1457 port_vlan = prestera_port_vlan_by_vid(port, vid);1458 if (WARN_ON(!port_vlan))1459 return;1460 1461 prestera_port_vlan_bridge_leave(port_vlan);1462 prestera_port_pvid_set(port, pvid);1463 prestera_port_vlan_destroy(port_vlan);1464}1465 1466static int prestera_port_vlans_add(struct prestera_port *port,1467 const struct switchdev_obj_port_vlan *vlan,1468 struct netlink_ext_ack *extack)1469{1470 bool flag_untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;1471 bool flag_pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;1472 struct net_device *orig_dev = vlan->obj.orig_dev;1473 struct prestera_bridge_port *br_port;1474 struct prestera_switch *sw = port->sw;1475 struct prestera_bridge *bridge;1476 1477 if (netif_is_bridge_master(orig_dev))1478 return 0;1479 1480 br_port = prestera_bridge_port_by_dev(sw->swdev, port->dev);1481 if (WARN_ON(!br_port))1482 return -EINVAL;1483 1484 bridge = br_port->bridge;1485 if (!bridge->vlan_enabled)1486 return 0;1487 1488 return prestera_bridge_port_vlan_add(port, br_port,1489 vlan->vid, flag_untagged,1490 flag_pvid, extack);1491}1492 1493static struct prestera_br_mdb_entry *1494prestera_br_mdb_entry_create(struct prestera_switch *sw,1495 struct prestera_bridge *br_dev,1496 const unsigned char *addr, u16 vid)1497{1498 struct prestera_br_mdb_entry *br_mdb_entry;1499 struct prestera_mdb_entry *mdb_entry;1500 1501 br_mdb_entry = kzalloc(sizeof(*br_mdb_entry), GFP_KERNEL);1502 if (!br_mdb_entry)1503 return NULL;1504 1505 mdb_entry = prestera_mdb_entry_create(sw, addr, vid);1506 if (!mdb_entry)1507 goto err_mdb_alloc;1508 1509 br_mdb_entry->mdb = mdb_entry;1510 br_mdb_entry->bridge = br_dev;1511 br_mdb_entry->enabled = true;1512 INIT_LIST_HEAD(&br_mdb_entry->br_mdb_port_list);1513 1514 list_add(&br_mdb_entry->br_mdb_entry_node, &br_dev->br_mdb_entry_list);1515 1516 return br_mdb_entry;1517 1518err_mdb_alloc:1519 kfree(br_mdb_entry);1520 return NULL;1521}1522 1523static int prestera_br_mdb_port_add(struct prestera_br_mdb_entry *br_mdb,1524 struct prestera_bridge_port *br_port)1525{1526 struct prestera_br_mdb_port *br_mdb_port;1527 1528 list_for_each_entry(br_mdb_port, &br_mdb->br_mdb_port_list,1529 br_mdb_port_node)1530 if (br_mdb_port->br_port == br_port)1531 return 0;1532 1533 br_mdb_port = kzalloc(sizeof(*br_mdb_port), GFP_KERNEL);1534 if (!br_mdb_port)1535 return -ENOMEM;1536 1537 br_mdb_port->br_port = br_port;1538 list_add(&br_mdb_port->br_mdb_port_node,1539 &br_mdb->br_mdb_port_list);1540 1541 return 0;1542}1543 1544static struct prestera_br_mdb_entry *1545prestera_br_mdb_entry_find(struct prestera_bridge *br_dev,1546 const unsigned char *addr, u16 vid)1547{1548 struct prestera_br_mdb_entry *br_mdb;1549 1550 list_for_each_entry(br_mdb, &br_dev->br_mdb_entry_list,1551 br_mdb_entry_node)1552 if (ether_addr_equal(&br_mdb->mdb->addr[0], addr) &&1553 vid == br_mdb->mdb->vid)1554 return br_mdb;1555 1556 return NULL;1557}1558 1559static struct prestera_br_mdb_entry *1560prestera_br_mdb_entry_get(struct prestera_switch *sw,1561 struct prestera_bridge *br_dev,1562 const unsigned char *addr, u16 vid)1563{1564 struct prestera_br_mdb_entry *br_mdb;1565 1566 br_mdb = prestera_br_mdb_entry_find(br_dev, addr, vid);1567 if (br_mdb)1568 return br_mdb;1569 1570 return prestera_br_mdb_entry_create(sw, br_dev, addr, vid);1571}1572 1573static int1574prestera_mdb_port_addr_obj_add(const struct switchdev_obj_port_mdb *mdb)1575{1576 struct prestera_br_mdb_entry *br_mdb;1577 struct prestera_bridge_port *br_port;1578 struct prestera_bridge *br_dev;1579 struct prestera_switch *sw;1580 struct prestera_port *port;1581 int err;1582 1583 sw = prestera_switch_get(mdb->obj.orig_dev);1584 port = prestera_port_dev_lower_find(mdb->obj.orig_dev);1585 1586 br_port = prestera_bridge_port_find(sw, mdb->obj.orig_dev);1587 if (!br_port)1588 return 0;1589 1590 br_dev = br_port->bridge;1591 1592 if (mdb->vid && !prestera_port_vlan_by_vid(port, mdb->vid))1593 return 0;1594 1595 if (mdb->vid)1596 br_mdb = prestera_br_mdb_entry_get(sw, br_dev, &mdb->addr[0],1597 mdb->vid);1598 else1599 br_mdb = prestera_br_mdb_entry_get(sw, br_dev, &mdb->addr[0],1600 br_dev->bridge_id);1601 1602 if (!br_mdb)1603 return -ENOMEM;1604 1605 /* Make sure newly allocated MDB entry gets disabled if either MC is1606 * disabled, or the mrouter does not exist.1607 */1608 WARN_ON(prestera_mdb_enable_set(br_mdb, br_dev->multicast_enabled &&1609 br_dev->mrouter_exist));1610 1611 err = prestera_br_mdb_port_add(br_mdb, br_port);1612 if (err) {1613 prestera_br_mdb_entry_put(br_mdb);1614 return err;1615 }1616 1617 err = prestera_br_mdb_sync(br_dev);1618 if (err)1619 return err;1620 1621 return 0;1622}1623 1624static int prestera_port_obj_add(struct net_device *dev, const void *ctx,1625 const struct switchdev_obj *obj,1626 struct netlink_ext_ack *extack)1627{1628 struct prestera_port *port = netdev_priv(dev);1629 const struct switchdev_obj_port_vlan *vlan;1630 const struct switchdev_obj_port_mdb *mdb;1631 int err = 0;1632 1633 switch (obj->id) {1634 case SWITCHDEV_OBJ_ID_PORT_VLAN:1635 vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);1636 return prestera_port_vlans_add(port, vlan, extack);1637 case SWITCHDEV_OBJ_ID_PORT_MDB:1638 mdb = SWITCHDEV_OBJ_PORT_MDB(obj);1639 err = prestera_mdb_port_addr_obj_add(mdb);1640 break;1641 case SWITCHDEV_OBJ_ID_HOST_MDB:1642 fallthrough;1643 default:1644 err = -EOPNOTSUPP;1645 break;1646 }1647 1648 return err;1649}1650 1651static int prestera_port_vlans_del(struct prestera_port *port,1652 const struct switchdev_obj_port_vlan *vlan)1653{1654 struct net_device *orig_dev = vlan->obj.orig_dev;1655 struct prestera_bridge_port *br_port;1656 struct prestera_switch *sw = port->sw;1657 1658 if (netif_is_bridge_master(orig_dev))1659 return -EOPNOTSUPP;1660 1661 br_port = prestera_bridge_port_by_dev(sw->swdev, port->dev);1662 if (WARN_ON(!br_port))1663 return -EINVAL;1664 1665 if (!br_port->bridge->vlan_enabled)1666 return 0;1667 1668 prestera_bridge_port_vlan_del(port, br_port, vlan->vid);1669 1670 return 0;1671}1672 1673static int1674prestera_mdb_port_addr_obj_del(struct prestera_port *port,1675 const struct switchdev_obj_port_mdb *mdb)1676{1677 struct prestera_br_mdb_entry *br_mdb;1678 struct prestera_bridge_port *br_port;1679 struct prestera_bridge *br_dev;1680 int err;1681 1682 /* Bridge port no longer exists - and so does this MDB entry */1683 br_port = prestera_bridge_port_find(port->sw, mdb->obj.orig_dev);1684 if (!br_port)1685 return 0;1686 1687 /* Removing MDB with non-existing VLAN - not supported; */1688 if (mdb->vid && !prestera_port_vlan_by_vid(port, mdb->vid))1689 return 0;1690 1691 br_dev = br_port->bridge;1692 1693 if (br_port->bridge->vlan_enabled)1694 br_mdb = prestera_br_mdb_entry_find(br_dev, &mdb->addr[0],1695 mdb->vid);1696 else1697 br_mdb = prestera_br_mdb_entry_find(br_dev, &mdb->addr[0],1698 br_port->bridge->bridge_id);1699 1700 if (!br_mdb)1701 return 0;1702 1703 /* Since there might be a situation that this port was the last in the1704 * MDB group, we have to both remove this port from software and HW MDB,1705 * sync MDB table, and then destroy software MDB (if needed).1706 */1707 prestera_br_mdb_port_del(br_mdb, br_port);1708 1709 prestera_br_mdb_entry_put(br_mdb);1710 1711 err = prestera_br_mdb_sync(br_dev);1712 if (err)1713 return err;1714 1715 return 0;1716}1717 1718static int prestera_port_obj_del(struct net_device *dev, const void *ctx,1719 const struct switchdev_obj *obj)1720{1721 struct prestera_port *port = netdev_priv(dev);1722 const struct switchdev_obj_port_mdb *mdb;1723 int err = 0;1724 1725 switch (obj->id) {1726 case SWITCHDEV_OBJ_ID_PORT_VLAN:1727 return prestera_port_vlans_del(port, SWITCHDEV_OBJ_PORT_VLAN(obj));1728 case SWITCHDEV_OBJ_ID_PORT_MDB:1729 mdb = SWITCHDEV_OBJ_PORT_MDB(obj);1730 err = prestera_mdb_port_addr_obj_del(port, mdb);1731 break;1732 default:1733 err = -EOPNOTSUPP;1734 break;1735 }1736 1737 return err;1738}1739 1740static int prestera_switchdev_blk_event(struct notifier_block *unused,1741 unsigned long event, void *ptr)1742{1743 struct net_device *dev = switchdev_notifier_info_to_dev(ptr);1744 int err;1745 1746 switch (event) {1747 case SWITCHDEV_PORT_OBJ_ADD:1748 err = switchdev_handle_port_obj_add(dev, ptr,1749 prestera_netdev_check,1750 prestera_port_obj_add);1751 break;1752 case SWITCHDEV_PORT_OBJ_DEL:1753 err = switchdev_handle_port_obj_del(dev, ptr,1754 prestera_netdev_check,1755 prestera_port_obj_del);1756 break;1757 case SWITCHDEV_PORT_ATTR_SET:1758 err = switchdev_handle_port_attr_set(dev, ptr,1759 prestera_netdev_check,1760 prestera_port_obj_attr_set);1761 break;1762 default:1763 return NOTIFY_DONE;1764 }1765 1766 return notifier_from_errno(err);1767}1768 1769static void prestera_fdb_event(struct prestera_switch *sw,1770 struct prestera_event *evt, void *arg)1771{1772 struct switchdev_notifier_fdb_info info = {};1773 struct net_device *dev = NULL;1774 struct prestera_port *port;1775 struct prestera_lag *lag;1776 1777 switch (evt->fdb_evt.type) {1778 case PRESTERA_FDB_ENTRY_TYPE_REG_PORT:1779 port = prestera_find_port(sw, evt->fdb_evt.dest.port_id);1780 if (port)1781 dev = port->dev;1782 break;1783 case PRESTERA_FDB_ENTRY_TYPE_LAG:1784 lag = prestera_lag_by_id(sw, evt->fdb_evt.dest.lag_id);1785 if (lag)1786 dev = lag->dev;1787 break;1788 default:1789 return;1790 }1791 1792 if (!dev)1793 return;1794 1795 info.addr = evt->fdb_evt.data.mac;1796 info.vid = evt->fdb_evt.vid;1797 info.offloaded = true;1798 1799 rtnl_lock();1800 1801 switch (evt->id) {1802 case PRESTERA_FDB_EVENT_LEARNED:1803 call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE,1804 dev, &info.info, NULL);1805 break;1806 case PRESTERA_FDB_EVENT_AGED:1807 call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE,1808 dev, &info.info, NULL);1809 break;1810 }1811 1812 rtnl_unlock();1813}1814 1815static int prestera_fdb_init(struct prestera_switch *sw)1816{1817 int err;1818 1819 err = prestera_hw_event_handler_register(sw, PRESTERA_EVENT_TYPE_FDB,1820 prestera_fdb_event, NULL);1821 if (err)1822 return err;1823 1824 err = prestera_hw_switch_ageing_set(sw, PRESTERA_DEFAULT_AGEING_TIME_MS);1825 if (err)1826 goto err_ageing_set;1827 1828 return 0;1829 1830err_ageing_set:1831 prestera_hw_event_handler_unregister(sw, PRESTERA_EVENT_TYPE_FDB,1832 prestera_fdb_event);1833 return err;1834}1835 1836static void prestera_fdb_fini(struct prestera_switch *sw)1837{1838 prestera_hw_event_handler_unregister(sw, PRESTERA_EVENT_TYPE_FDB,1839 prestera_fdb_event);1840}1841 1842static int prestera_switchdev_handler_init(struct prestera_switchdev *swdev)1843{1844 int err;1845 1846 swdev->swdev_nb.notifier_call = prestera_switchdev_event;1847 err = register_switchdev_notifier(&swdev->swdev_nb);1848 if (err)1849 goto err_register_swdev_notifier;1850 1851 swdev->swdev_nb_blk.notifier_call = prestera_switchdev_blk_event;1852 err = register_switchdev_blocking_notifier(&swdev->swdev_nb_blk);1853 if (err)1854 goto err_register_blk_swdev_notifier;1855 1856 return 0;1857 1858err_register_blk_swdev_notifier:1859 unregister_switchdev_notifier(&swdev->swdev_nb);1860err_register_swdev_notifier:1861 destroy_workqueue(swdev_wq);1862 return err;1863}1864 1865static void prestera_switchdev_handler_fini(struct prestera_switchdev *swdev)1866{1867 unregister_switchdev_blocking_notifier(&swdev->swdev_nb_blk);1868 unregister_switchdev_notifier(&swdev->swdev_nb);1869}1870 1871int prestera_switchdev_init(struct prestera_switch *sw)1872{1873 struct prestera_switchdev *swdev;1874 int err;1875 1876 swdev = kzalloc(sizeof(*swdev), GFP_KERNEL);1877 if (!swdev)1878 return -ENOMEM;1879 1880 sw->swdev = swdev;1881 swdev->sw = sw;1882 1883 INIT_LIST_HEAD(&swdev->bridge_list);1884 1885 swdev_wq = alloc_ordered_workqueue("%s_ordered", 0, "prestera_br");1886 if (!swdev_wq) {1887 err = -ENOMEM;1888 goto err_alloc_wq;1889 }1890 1891 err = prestera_switchdev_handler_init(swdev);1892 if (err)1893 goto err_swdev_init;1894 1895 err = prestera_fdb_init(sw);1896 if (err)1897 goto err_fdb_init;1898 1899 return 0;1900 1901err_fdb_init:1902err_swdev_init:1903 destroy_workqueue(swdev_wq);1904err_alloc_wq:1905 kfree(swdev);1906 1907 return err;1908}1909 1910void prestera_switchdev_fini(struct prestera_switch *sw)1911{1912 struct prestera_switchdev *swdev = sw->swdev;1913 1914 prestera_fdb_fini(sw);1915 prestera_switchdev_handler_fini(swdev);1916 destroy_workqueue(swdev_wq);1917 kfree(swdev);1918}1919