--- zzzz-none-000/linux-4.4.60/net/bridge/br_sysfs_if.c 2017-04-08 07:53:53.000000000 +0000 +++ scorpion-7490-727/linux-4.4.60/net/bridge/br_sysfs_if.c 2021-02-04 17:41:59.000000000 +0000 @@ -173,6 +173,22 @@ BRPORT_ATTR_FLAG(proxyarp, BR_PROXYARP); BRPORT_ATTR_FLAG(proxyarp_wifi, BR_PROXYARP_WIFI); +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 ssize_t 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 +204,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 +321,18 @@ #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 NULL };