--- zzzz-none-000/linux-4.4.271/net/bridge/br_sysfs_if.c 2021-06-03 06:22:09.000000000 +0000 +++ hawkeye-5590-750/linux-4.4.271/net/bridge/br_sysfs_if.c 2023-04-19 10:22:30.000000000 +0000 @@ -172,6 +172,24 @@ BRPORT_ATTR_FLAG(unicast_flood, BR_FLOOD); BRPORT_ATTR_FLAG(proxyarp, BR_PROXYARP); BRPORT_ATTR_FLAG(proxyarp_wifi, BR_PROXYARP_WIFI); +BRPORT_ATTR_FLAG(multicast_flood, BR_MCAST_FLOOD); +BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD); + +static ssize_t show_isolate_mode(struct net_bridge_port *p, char *buf) +{ + int isolate_mode = (p->flags & BR_ISOLATE_MODE) ? 1 : 0; + return sprintf(buf, "%d\n", isolate_mode); +} +static int store_isolate_mode(struct net_bridge_port *p, unsigned long v) +{ + if (v) + p->flags |= BR_ISOLATE_MODE; + else + p->flags &= ~BR_ISOLATE_MODE; + return 0; +} +static BRPORT_ATTR(isolate_mode, S_IRUGO | S_IWUSR, + show_isolate_mode, store_isolate_mode); #ifdef CONFIG_BRIDGE_IGMP_SNOOPING static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) @@ -188,6 +206,97 @@ store_multicast_router); BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE); + +#ifdef CONFIG_AVM_BRIDGE_MULTICAST_TO_UNICAST + +BRPORT_ATTR_FLAG(avm_multicast_to_unicast, BR_MULTICAST_TO_UNICAST); + +static ssize_t show_multicast_to_unicast_threshold(struct net_bridge_port *p, char *buf) +{ + return sprintf(buf, "%d\n", p->multicast_to_unicast_threshold); +} + +static int store_multicast_to_unicast_threshold(struct net_bridge_port *p, unsigned long v) +{ + p->multicast_to_unicast_threshold = v; + return 0; +} +static BRPORT_ATTR(avm_multicast_to_unicast_threshold, S_IRUGO | S_IWUSR, + show_multicast_to_unicast_threshold, + store_multicast_to_unicast_threshold); + +static ssize_t show_recipients(struct net_bridge_port *p, char *buf) +{ + int i; + struct net_bridge *br = p->br; + struct net_bridge_mdb_htable *mdb; + char line[128]; + + if (!netif_running(br->dev) || (p->state == BR_STATE_DISABLED)) + return -EBUSY; + + buf[0] = '\0'; + + spin_lock_irq(&br->multicast_lock); + rcu_read_lock(); + + mdb = rcu_dereference(br->mdb); + if (!mdb) + goto out; + + for (i = 0; i < mdb->max; i++) { + struct net_bridge_mdb_entry *mp; + struct net_bridge_port_group *pg; + struct net_bridge_group_recipient *recp; + struct net_bridge_fdb_entry *fdb; + + hlist_for_each_entry_rcu(mp, &mdb->mhash[i], hlist[mdb->ver]) { + + for (pg = mlock_dereference(mp->ports, br); + pg != NULL; + pg = mlock_dereference(pg->next, br)) { + if (pg->port != p) + continue; + + list_for_each_entry_rcu(recp, &pg->recipients, list) { + fdb = rcu_dereference(recp->recipient); + + switch (mp->addr.proto) { + case htons(ETH_P_IP): + snprintf(line, sizeof(line), + "%pI4: %pM\n", &mp->addr.u.ip4, &fdb->addr.addr); + break; +#if IS_ENABLED(CONFIG_IPV6) + case htons(ETH_P_IPV6): + snprintf(line, sizeof(line), + "%pI6: %pM\n", &mp->addr.u.ip6, &fdb->addr.addr); + break; +#endif + default: + /* unreachable */ + continue; + } + if (strlcat(buf, line, PAGE_SIZE) >= PAGE_SIZE) + goto out; + } + } + } + } + +out: + rcu_read_unlock(); + spin_unlock_irq(&br->multicast_lock); + + return strlen(buf); +} + +static BRPORT_ATTR(avm_multicast_recipients, S_IRUGO, show_recipients, NULL); + +#endif +#endif + +#ifdef CONFIG_AVM_BRIDGE_ISOLATION +static BRPORT_ATTR(avm_isolated, S_IRUGO | S_IWUSR, br_isol_show, br_isol_store); #endif static const struct brport_attribute *brport_attrs[] = { @@ -214,9 +323,20 @@ #ifdef CONFIG_BRIDGE_IGMP_SNOOPING &brport_attr_multicast_router, &brport_attr_multicast_fast_leave, +#ifdef CONFIG_AVM_BRIDGE_MULTICAST_TO_UNICAST + &brport_attr_avm_multicast_to_unicast, + &brport_attr_avm_multicast_to_unicast_threshold, + &brport_attr_avm_multicast_recipients, +#endif #endif &brport_attr_proxyarp, &brport_attr_proxyarp_wifi, + &brport_attr_isolate_mode, +#ifdef CONFIG_AVM_BRIDGE_ISOLATION + &brport_attr_avm_isolated, +#endif + &brport_attr_multicast_flood, + &brport_attr_broadcast_flood, NULL };