/* * Handle changes in state of network devices enslaved to a bridge. * * Note: don't care about up/down if bridge itself is down, because * port state is checked when bridge is brought up.
*/ staticint br_device_event(struct notifier_block *unused, unsignedlong event, void *ptr)
{ struct netlink_ext_ack *extack = netdev_notifier_info_to_extack(ptr); struct netdev_notifier_pre_changeaddr_info *prechaddr_info; struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net_bridge_port *p; struct net_bridge *br; bool notified = false; bool changed_addr; int err;
if (netif_is_bridge_master(dev)) { struct net_bridge *br = netdev_priv(dev);
if (event == NETDEV_REGISTER)
br_fdb_change_mac_address(br, dev->dev_addr);
err = br_vlan_bridge_event(dev, event, ptr); if (err) return notifier_from_errno(err);
if (event == NETDEV_REGISTER) { /* register of bridge completed, add sysfs entries */
err = br_sysfs_addbr(dev); if (err) return notifier_from_errno(err);
return NOTIFY_DONE;
}
}
if (is_vlan_dev(dev)) { struct net_device *real_dev = vlan_dev_real_dev(dev);
if (netif_is_bridge_master(real_dev))
br_vlan_vlan_upper_event(real_dev, dev, event);
}
/* not a port of a bridge */
p = br_port_get_rtnl(dev); if (!p) return NOTIFY_DONE;
br = p->br;
switch (event) { case NETDEV_CHANGEMTU:
br_mtu_auto_adjust(br); break;
case NETDEV_PRE_CHANGEADDR: if (br->dev->addr_assign_type == NET_ADDR_SET) break;
prechaddr_info = ptr;
err = netif_pre_changeaddr_notify(br->dev,
prechaddr_info->dev_addr,
extack); if (err) return notifier_from_errno(err); break;
case NETDEV_CHANGEADDR:
spin_lock_bh(&br->lock);
br_fdb_changeaddr(p, dev->dev_addr);
changed_addr = br_stp_recalculate_bridge_id(br);
spin_unlock_bh(&br->lock);
if (changed_addr)
call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
break;
case NETDEV_CHANGE:
br_port_carrier_check(p, ¬ified); break;
case NETDEV_FEAT_CHANGE:
netdev_update_features(br->dev); break;
case NETDEV_DOWN:
spin_lock_bh(&br->lock); if (br->dev->flags & IFF_UP) {
br_stp_disable_port(p);
notified = true;
}
spin_unlock_bh(&br->lock); break;
case NETDEV_UP: if (netif_running(br->dev) && netif_oper_up(dev)) {
spin_lock_bh(&br->lock);
br_stp_enable_port(p);
notified = true;
spin_unlock_bh(&br->lock);
} break;
case NETDEV_UNREGISTER:
br_del_if(br, dev); break;
case NETDEV_CHANGENAME:
err = br_sysfs_renameif(p); if (err) return notifier_from_errno(err); break;
case NETDEV_PRE_TYPE_CHANGE: /* Forbid underlying device to change its type. */ return NOTIFY_BAD;
case NETDEV_RESEND_IGMP: /* Propagate to master device */
call_netdevice_notifiers(event, br->dev); break;
}
if (event != NETDEV_UNREGISTER)
br_vlan_port_event(p, event);
/* Events that may cause spanning tree to refresh */ if (!notified && (event == NETDEV_CHANGEADDR || event == NETDEV_UP ||
event == NETDEV_CHANGE || event == NETDEV_DOWN))
br_ifinfo_notify(RTM_NEWLINK, NULL, p);
/* br_boolopt_toggle - change user-controlled boolean option * * @br: bridge device * @opt: id of the option to change * @on: new option value * @extack: extack for error messages * * Changes the value of the respective boolean option to @on taking care of * any internal option value mapping and configuration.
*/ int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on, struct netlink_ext_ack *extack)
{ int err = 0;
switch (opt) { case BR_BOOLOPT_NO_LL_LEARN:
br_opt_toggle(br, BROPT_NO_LL_LEARN, on); break; case BR_BOOLOPT_MCAST_VLAN_SNOOPING:
err = br_multicast_toggle_vlan_snooping(br, on, extack); break; case BR_BOOLOPT_MST_ENABLE:
err = br_mst_set_enabled(br, on, extack); break; case BR_BOOLOPT_MDB_OFFLOAD_FAIL_NOTIFICATION:
br_opt_toggle(br, BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION, on); break; default: /* shouldn't be called with unsupported options */
WARN_ON(1); break;
}
return err;
}
int br_boolopt_get(conststruct net_bridge *br, enum br_boolopt_id opt)
{ switch (opt) { case BR_BOOLOPT_NO_LL_LEARN: return br_opt_get(br, BROPT_NO_LL_LEARN); case BR_BOOLOPT_MCAST_VLAN_SNOOPING: return br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED); case BR_BOOLOPT_MST_ENABLE: return br_opt_get(br, BROPT_MST_ENABLED); case BR_BOOLOPT_MDB_OFFLOAD_FAIL_NOTIFICATION: return br_opt_get(br, BROPT_MDB_OFFLOAD_FAIL_NOTIFICATION); default: /* shouldn't be called with unsupported options */
WARN_ON(1); break;
}
return 0;
}
int br_boolopt_multi_toggle(struct net_bridge *br, struct br_boolopt_multi *bm, struct netlink_ext_ack *extack)
{ unsignedlong bitmap = bm->optmask; int err = 0; int opt_id;
#if IS_MODULE(CONFIG_BRIDGE_NETFILTER)
pr_info("bridge: filtering via arp/ip/ip6tables is no longer available " "by default. Update your scripts to load br_netfilter if you " "need this.\n"); #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.