| @@ -759,13 +759,17 @@ static void br_multicast_router_expired(unsigned long data) · 758 unmodified lines |
| 759 | 759 | struct net_bridge *br = port->br; |
| 760 | 760 | |
| 761 | 761 | spin_lock(&br->multicast_lock); |
| 762 | | − if (port->multicast_router != 1 || |
| 762 | + if (port->multicast_router == MDB_RTR_TYPE_DISABLED || |
| 763 | + port->multicast_router == MDB_RTR_TYPE_PERM || |
| 763 | 764 | timer_pending(&port->multicast_router_timer) || |
| 764 | 765 | hlist_unhashed(&port->rlist)) |
| 765 | 766 | goto out; |
| 766 | 767 | |
| 767 | 768 | hlist_del_init_rcu(&port->rlist); |
| 768 | 769 | br_rtr_notify(br->dev, port, RTM_DELMDB); |
| 770 | + /* Don't allow timer refresh if the router expired */ |
| 771 | + if (port->multicast_router == MDB_RTR_TYPE_TEMP) |
| 772 | + port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; |
| 769 | 773 | |
| 770 | 774 | out: |
| 771 | 775 | spin_unlock(&br->multicast_lock); |
| @@ -912,7 +916,7 @@ static void br_ip6_multicast_port_query_expired(unsigned long data) · 140 unmodified lines |
| 912 | 916 | |
| 913 | 917 | void br_multicast_add_port(struct net_bridge_port *port) |
| 914 | 918 | { |
| 915 | | − port->multicast_router = 1; |
| 919 | + port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; |
| 916 | 920 | |
| 917 | 921 | setup_timer(&port->multicast_router_timer, br_multicast_router_expired, |
| 918 | 922 | (unsigned long)port); |
| @@ -959,7 +963,8 @@ void br_multicast_enable_port(struct net_bridge_port *port) · 40 unmodified lines |
| 959 | 963 | #if IS_ENABLED(CONFIG_IPV6) |
| 960 | 964 | br_multicast_enable(&port->ip6_own_query); |
| 961 | 965 | #endif |
| 962 | | − if (port->multicast_router == 2 && hlist_unhashed(&port->rlist)) |
| 966 | + if (port->multicast_router == MDB_RTR_TYPE_PERM && |
| 967 | + hlist_unhashed(&port->rlist)) |
| 963 | 968 | br_multicast_add_router(br, port); |
| 964 | 969 | |
| 965 | 970 | out: |
| @@ -980,6 +985,9 @@ void br_multicast_disable_port(struct net_bridge_port *port) · 14 unmodified lines |
| 980 | 985 | if (!hlist_unhashed(&port->rlist)) { |
| 981 | 986 | hlist_del_init_rcu(&port->rlist); |
| 982 | 987 | br_rtr_notify(br->dev, port, RTM_DELMDB); |
| 988 | + /* Don't allow timer refresh if disabling */ |
| 989 | + if (port->multicast_router == MDB_RTR_TYPE_TEMP) |
| 990 | + port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; |
| 983 | 991 | } |
| 984 | 992 | del_timer(&port->multicast_router_timer); |
| 985 | 993 | del_timer(&port->ip4_own_query.timer); |
| @@ -1227,13 +1235,14 @@ static void br_multicast_mark_router(struct net_bridge *br, · 241 unmodified lines |
| 1227 | 1235 | unsigned long now = jiffies; |
| 1228 | 1236 | |
| 1229 | 1237 | if (!port) { |
| 1230 | | − if (br->multicast_router == 1) |
| 1238 | + if (br->multicast_router == MDB_RTR_TYPE_TEMP_QUERY) |
| 1231 | 1239 | mod_timer(&br->multicast_router_timer, |
| 1232 | 1240 | now + br->multicast_querier_interval); |
| 1233 | 1241 | return; |
| 1234 | 1242 | } |
| 1235 | 1243 | |
| 1236 | | − if (port->multicast_router != 1) |
| 1244 | + if (port->multicast_router == MDB_RTR_TYPE_DISABLED || |
| 1245 | + port->multicast_router == MDB_RTR_TYPE_PERM) |
| 1237 | 1246 | return; |
| 1238 | 1247 | |
| 1239 | 1248 | br_multicast_add_router(br, port); |
| @@ -1713,7 +1722,7 @@ void br_multicast_init(struct net_bridge *br) · 473 unmodified lines |
| 1713 | 1722 | br->hash_elasticity = 4; |
| 1714 | 1723 | br->hash_max = 512; |
| 1715 | 1724 | |
| 1716 | | − br->multicast_router = 1; |
| 1725 | + br->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; |
| 1717 | 1726 | br->multicast_querier = 0; |
| 1718 | 1727 | br->multicast_query_use_ifaddr = 0; |
| 1719 | 1728 | br->multicast_last_member_count = 2; |
| @@ -1823,11 +1832,11 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val) · 103 unmodified lines |
| 1823 | 1832 | spin_lock_bh(&br->multicast_lock); |
| 1824 | 1833 | |
| 1825 | 1834 | switch (val) { |
| 1826 | | − case 0: |
| 1827 | | − case 2: |
| 1835 | + case MDB_RTR_TYPE_DISABLED: |
| 1836 | + case MDB_RTR_TYPE_PERM: |
| 1828 | 1837 | del_timer(&br->multicast_router_timer); |
| 1829 | 1838 | /* fall through */ |
| 1830 | | − case 1: |
| 1839 | + case MDB_RTR_TYPE_TEMP_QUERY: |
| 1831 | 1840 | br->multicast_router = val; |
| 1832 | 1841 | err = 0; |
| 1833 | 1842 | break; |
| @@ -1838,37 +1847,53 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val) · 4 unmodified lines |
| 1838 | 1847 | return err; |
| 1839 | 1848 | } |
| 1840 | 1849 | |
| 1850 | +static void __del_port_router(struct net_bridge_port *p) |
| 1851 | +{ |
| 1852 | + if (hlist_unhashed(&p->rlist)) |
| 1853 | + return; |
| 1854 | + hlist_del_init_rcu(&p->rlist); |
| 1855 | + br_rtr_notify(p->br->dev, p, RTM_DELMDB); |
| 1856 | +} |
| 1857 | + |
| 1841 | 1858 | int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) |
| 1842 | 1859 | { |
| 1843 | 1860 | struct net_bridge *br = p->br; |
| 1861 | + unsigned long now = jiffies; |
| 1844 | 1862 | int err = -EINVAL; |
| 1845 | 1863 | |
| 1846 | 1864 | spin_lock(&br->multicast_lock); |
| 1847 | | − |
| 1848 | | − switch (val) { |
| 1849 | | − case 0: |
| 1850 | | − case 1: |
| 1851 | | − case 2: |
| 1852 | | − p->multicast_router = val; |
| 1865 | + if (p->multicast_router == val) { |
| 1866 | + /* Refresh the temp router port timer */ |
| 1867 | + if (p->multicast_router == MDB_RTR_TYPE_TEMP) |
| 1868 | + mod_timer(&p->multicast_router_timer, |
| 1869 | + now + br->multicast_querier_interval); |
| 1853 | 1870 | err = 0; |
| 1854 | | − |
| 1855 | | − if (val < 2 && !hlist_unhashed(&p->rlist)) { |
| 1856 | | − hlist_del_init_rcu(&p->rlist); |
| 1857 | | − br_rtr_notify(br->dev, p, RTM_DELMDB); |
| 1858 | | − } |
| 1859 | | − |
| 1860 | | − if (val == 1) |
| 1861 | | − break; |
| 1862 | | − |
| 1871 | + goto unlock; |
| 1872 | + } |
| 1873 | + switch (val) { |
| 1874 | + case MDB_RTR_TYPE_DISABLED: |
| 1875 | + p->multicast_router = MDB_RTR_TYPE_DISABLED; |
| 1876 | + __del_port_router(p); |
| 1877 | + del_timer(&p->multicast_router_timer); |
| 1878 | + break; |
| 1879 | + case MDB_RTR_TYPE_TEMP_QUERY: |
| 1880 | + p->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; |
| 1881 | + __del_port_router(p); |
| 1882 | + break; |
| 1883 | + case MDB_RTR_TYPE_PERM: |
| 1884 | + p->multicast_router = MDB_RTR_TYPE_PERM; |
| 1863 | 1885 | del_timer(&p->multicast_router_timer); |
| 1864 | | − |
| 1865 | | − if (val == 0) |
| 1866 | | − break; |
| 1867 | | − |
| 1868 | 1886 | br_multicast_add_router(br, p); |
| 1869 | 1887 | break; |
| 1888 | + case MDB_RTR_TYPE_TEMP: |
| 1889 | + p->multicast_router = MDB_RTR_TYPE_TEMP; |
| 1890 | + br_multicast_mark_router(br, p); |
| 1891 | + break; |
| 1892 | + default: |
| 1893 | + goto unlock; |
| 1870 | 1894 | } |
| 1871 | | − |
| 1895 | + err = 0; |
| 1896 | +unlock: |
| 1872 | 1897 | spin_unlock(&br->multicast_lock); |
| 1873 | 1898 | |
| 1874 | 1899 | return err; |