--- zzzz-none-000/linux-3.10.107/net/bridge/br_sysfs_if.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/net/bridge/br_sysfs_if.c 2021-02-04 17:41:59.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 }, \ @@ -41,20 +41,30 @@ } \ static int store_##_name(struct net_bridge_port *p, unsigned long v) \ { \ - unsigned long flags = p->flags; \ - if (v) \ - flags |= _mask; \ - else \ - flags &= ~_mask; \ - if (flags != p->flags) { \ - p->flags = flags; \ - br_ifinfo_notify(RTM_NEWLINK, p); \ - } \ - return 0; \ + return store_flag(p, v, _mask); \ } \ static BRPORT_ATTR(_name, S_IRUGO | S_IWUSR, \ show_##_name, store_##_name) +static int store_flag(struct net_bridge_port *p, unsigned long v, + unsigned long mask) +{ + unsigned long flags; + + flags = p->flags; + + if (v) + flags |= mask; + else + flags &= ~mask; + + if (flags != p->flags) { + p->flags = flags; + br_port_flags_change(p, mask); + br_ifinfo_notify(RTM_NEWLINK, p); + } + return 0; +} static ssize_t show_path_cost(struct net_bridge_port *p, char *buf) { @@ -150,7 +160,7 @@ static int store_flush(struct net_bridge_port *p, unsigned long v) { - br_fdb_delete_by_port(p->br, p, 0); // Don't delete local entry + br_fdb_delete_by_port(p->br, p, 0, 0); // Don't delete local entry return 0; } static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush); @@ -158,6 +168,26 @@ 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); +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) @@ -174,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[] = { @@ -195,9 +316,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 + &brport_attr_proxyarp, + &brport_attr_proxyarp_wifi, + &brport_attr_isolate_mode, +#ifdef CONFIG_AVM_BRIDGE_ISOLATION + &brport_attr_avm_isolated, #endif NULL }; @@ -205,21 +339,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;