--- zzzz-none-000/linux-3.10.107/net/bridge/br_sysfs_if.c 2017-06-27 09:49:32.000000000 +0000 +++ vr9-7490-729/linux-3.10.107/net/bridge/br_sysfs_if.c 2021-11-10 11:53:56.000000000 +0000 @@ -26,7 +26,7 @@ int (*store)(struct net_bridge_port *, unsigned long); }; -#define BRPORT_ATTR(_name,_mode,_show,_store) \ +#define BRPORT_ATTR(_name, _mode, _show, _store) \ const struct brport_attribute brport_attr_##_name = { \ .attr = {.name = __stringify(_name), \ .mode = _mode }, \ @@ -158,6 +158,8 @@ BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE); BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD); BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK); +BRPORT_ATTR_FLAG(learning, BR_LEARNING); +BRPORT_ATTR_FLAG(unicast_flood, BR_FLOOD); #ifdef CONFIG_BRIDGE_IGMP_SNOOPING static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) @@ -174,6 +176,100 @@ 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); +#ifdef CONFIG_AVM_BRIDGE_ISOLATION_UPSTREAM +static BRPORT_ATTR(avm_upstream, S_IRUGO | S_IWUSR, br_isol_us_show, br_isol_us_store); +#endif #endif static const struct brport_attribute *brport_attrs[] = { @@ -195,9 +291,22 @@ &brport_attr_hairpin_mode, &brport_attr_bpdu_guard, &brport_attr_root_block, + &brport_attr_learning, + &brport_attr_unicast_flood, #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 +#ifdef CONFIG_AVM_BRIDGE_ISOLATION + &brport_attr_avm_isolated, +#ifdef CONFIG_AVM_BRIDGE_ISOLATION_UPSTREAM + &brport_attr_avm_upstream, +#endif #endif NULL }; @@ -205,21 +314,21 @@ #define to_brport_attr(_at) container_of(_at, struct brport_attribute, attr) #define to_brport(obj) container_of(obj, struct net_bridge_port, kobj) -static ssize_t brport_show(struct kobject * kobj, - struct attribute * attr, char * buf) +static ssize_t brport_show(struct kobject *kobj, + struct attribute *attr, char *buf) { - struct brport_attribute * brport_attr = to_brport_attr(attr); - struct net_bridge_port * p = to_brport(kobj); + struct brport_attribute *brport_attr = to_brport_attr(attr); + struct net_bridge_port *p = to_brport(kobj); return brport_attr->show(p, buf); } -static ssize_t brport_store(struct kobject * kobj, - struct attribute * attr, - const char * buf, size_t count) +static ssize_t brport_store(struct kobject *kobj, + struct attribute *attr, + const char *buf, size_t count) { - struct brport_attribute * brport_attr = to_brport_attr(attr); - struct net_bridge_port * p = to_brport(kobj); + struct brport_attribute *brport_attr = to_brport_attr(attr); + struct net_bridge_port *p = to_brport(kobj); ssize_t ret = -EINVAL; char *endp; unsigned long val;