Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'bridge-mcast-tmp-router-port'

Nikolay Aleksandrov says:

====================
bridge: mcast: add support for temp router port

This set adds support for temporary router port which doesn't depend only
on the incoming queries. It can be refreshed by setting multicast_router to
the same value (3). The first two patches are minor changes that prepare
the code for the third which adds this new type of router port.
In order to be able to dump its information the mdb router port format
is changed in patch 04 and extended similar to how mdb entries format was
done recently.
The related iproute2 changes will be posted if this is accepted.

v2: set val first and adjust router type later in patch 01, patch 03 was
split in 2
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+89 -32
+21 -1
include/uapi/linux/if_bridge.h
··· 144 144 * } 145 145 * } 146 146 * [MDBA_ROUTER] = { 147 - * [MDBA_ROUTER_PORT] 147 + * [MDBA_ROUTER_PORT] = { 148 + * u32 ifindex 149 + * [MDBA_ROUTER_PATTR attributes] 150 + * } 148 151 * } 149 152 */ 150 153 enum { ··· 180 177 }; 181 178 #define MDBA_MDB_EATTR_MAX (__MDBA_MDB_EATTR_MAX - 1) 182 179 180 + /* multicast router types */ 181 + enum { 182 + MDB_RTR_TYPE_DISABLED, 183 + MDB_RTR_TYPE_TEMP_QUERY, 184 + MDB_RTR_TYPE_PERM, 185 + MDB_RTR_TYPE_TEMP 186 + }; 187 + 183 188 enum { 184 189 MDBA_ROUTER_UNSPEC, 185 190 MDBA_ROUTER_PORT, 186 191 __MDBA_ROUTER_MAX, 187 192 }; 188 193 #define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1) 194 + 195 + /* router port attributes */ 196 + enum { 197 + MDBA_ROUTER_PATTR_UNSPEC, 198 + MDBA_ROUTER_PATTR_TIMER, 199 + MDBA_ROUTER_PATTR_TYPE, 200 + __MDBA_ROUTER_PATTR_MAX 201 + }; 202 + #define MDBA_ROUTER_PATTR_MAX (__MDBA_ROUTER_PATTR_MAX - 1) 189 203 190 204 struct br_port_msg { 191 205 __u8 family;
+14 -2
net/bridge/br_mdb.c
··· 20 20 { 21 21 struct net_bridge *br = netdev_priv(dev); 22 22 struct net_bridge_port *p; 23 - struct nlattr *nest; 23 + struct nlattr *nest, *port_nest; 24 24 25 25 if (!br->multicast_router || hlist_empty(&br->router_list)) 26 26 return 0; ··· 30 30 return -EMSGSIZE; 31 31 32 32 hlist_for_each_entry_rcu(p, &br->router_list, rlist) { 33 - if (p && nla_put_u32(skb, MDBA_ROUTER_PORT, p->dev->ifindex)) 33 + if (!p) 34 + continue; 35 + port_nest = nla_nest_start(skb, MDBA_ROUTER_PORT); 36 + if (!port_nest) 34 37 goto fail; 38 + if (nla_put_nohdr(skb, sizeof(u32), &p->dev->ifindex) || 39 + nla_put_u32(skb, MDBA_ROUTER_PATTR_TIMER, 40 + br_timer_value(&p->multicast_router_timer)) || 41 + nla_put_u8(skb, MDBA_ROUTER_PATTR_TYPE, 42 + p->multicast_router)) { 43 + nla_nest_cancel(skb, port_nest); 44 + goto fail; 45 + } 46 + nla_nest_end(skb, port_nest); 35 47 } 36 48 37 49 nla_nest_end(skb, nest);
+54 -29
net/bridge/br_multicast.c
··· 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); ··· 916 912 917 913 void br_multicast_add_port(struct net_bridge_port *port) 918 914 { 919 - port->multicast_router = 1; 915 + port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; 920 916 921 917 setup_timer(&port->multicast_router_timer, br_multicast_router_expired, 922 918 (unsigned long)port); ··· 963 959 #if IS_ENABLED(CONFIG_IPV6) 964 960 br_multicast_enable(&port->ip6_own_query); 965 961 #endif 966 - if (port->multicast_router == 2 && hlist_unhashed(&port->rlist)) 962 + if (port->multicast_router == MDB_RTR_TYPE_PERM && 963 + hlist_unhashed(&port->rlist)) 967 964 br_multicast_add_router(br, port); 968 965 969 966 out: ··· 985 980 if (!hlist_unhashed(&port->rlist)) { 986 981 hlist_del_init_rcu(&port->rlist); 987 982 br_rtr_notify(br->dev, port, RTM_DELMDB); 983 + /* Don't allow timer refresh if disabling */ 984 + if (port->multicast_router == MDB_RTR_TYPE_TEMP) 985 + port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; 988 986 } 989 987 del_timer(&port->multicast_router_timer); 990 988 del_timer(&port->ip4_own_query.timer); ··· 1235 1227 unsigned long now = jiffies; 1236 1228 1237 1229 if (!port) { 1238 - if (br->multicast_router == 1) 1230 + if (br->multicast_router == MDB_RTR_TYPE_TEMP_QUERY) 1239 1231 mod_timer(&br->multicast_router_timer, 1240 1232 now + br->multicast_querier_interval); 1241 1233 return; 1242 1234 } 1243 1235 1244 - if (port->multicast_router != 1) 1236 + if (port->multicast_router == MDB_RTR_TYPE_DISABLED || 1237 + port->multicast_router == MDB_RTR_TYPE_PERM) 1245 1238 return; 1246 1239 1247 1240 br_multicast_add_router(br, port); ··· 1722 1713 br->hash_elasticity = 4; 1723 1714 br->hash_max = 512; 1724 1715 1725 - br->multicast_router = 1; 1716 + br->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; 1726 1717 br->multicast_querier = 0; 1727 1718 br->multicast_query_use_ifaddr = 0; 1728 1719 br->multicast_last_member_count = 2; ··· 1832 1823 spin_lock_bh(&br->multicast_lock); 1833 1824 1834 1825 switch (val) { 1835 - case 0: 1836 - case 2: 1826 + case MDB_RTR_TYPE_DISABLED: 1827 + case MDB_RTR_TYPE_PERM: 1837 1828 del_timer(&br->multicast_router_timer); 1838 1829 /* fall through */ 1839 - case 1: 1830 + case MDB_RTR_TYPE_TEMP_QUERY: 1840 1831 br->multicast_router = val; 1841 1832 err = 0; 1842 1833 break; ··· 1847 1838 return err; 1848 1839 } 1849 1840 1841 + static void __del_port_router(struct net_bridge_port *p) 1842 + { 1843 + if (hlist_unhashed(&p->rlist)) 1844 + return; 1845 + hlist_del_init_rcu(&p->rlist); 1846 + br_rtr_notify(p->br->dev, p, RTM_DELMDB); 1847 + } 1848 + 1850 1849 int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) 1851 1850 { 1852 1851 struct net_bridge *br = p->br; 1852 + unsigned long now = jiffies; 1853 1853 int err = -EINVAL; 1854 1854 1855 1855 spin_lock(&br->multicast_lock); 1856 - 1857 - switch (val) { 1858 - case 0: 1859 - case 1: 1860 - case 2: 1861 - p->multicast_router = val; 1856 + if (p->multicast_router == val) { 1857 + /* Refresh the temp router port timer */ 1858 + if (p->multicast_router == MDB_RTR_TYPE_TEMP) 1859 + mod_timer(&p->multicast_router_timer, 1860 + now + br->multicast_querier_interval); 1862 1861 err = 0; 1863 - 1864 - if (val < 2 && !hlist_unhashed(&p->rlist)) { 1865 - hlist_del_init_rcu(&p->rlist); 1866 - br_rtr_notify(br->dev, p, RTM_DELMDB); 1867 - } 1868 - 1869 - if (val == 1) 1870 - break; 1871 - 1862 + goto unlock; 1863 + } 1864 + switch (val) { 1865 + case MDB_RTR_TYPE_DISABLED: 1866 + p->multicast_router = MDB_RTR_TYPE_DISABLED; 1867 + __del_port_router(p); 1872 1868 del_timer(&p->multicast_router_timer); 1873 - 1874 - if (val == 0) 1875 - break; 1876 - 1869 + break; 1870 + case MDB_RTR_TYPE_TEMP_QUERY: 1871 + p->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; 1872 + __del_port_router(p); 1873 + break; 1874 + case MDB_RTR_TYPE_PERM: 1875 + p->multicast_router = MDB_RTR_TYPE_PERM; 1876 + del_timer(&p->multicast_router_timer); 1877 1877 br_multicast_add_router(br, p); 1878 1878 break; 1879 + case MDB_RTR_TYPE_TEMP: 1880 + p->multicast_router = MDB_RTR_TYPE_TEMP; 1881 + br_multicast_mark_router(br, p); 1882 + break; 1883 + default: 1884 + goto unlock; 1879 1885 } 1880 - 1886 + err = 0; 1887 + unlock: 1881 1888 spin_unlock(&br->multicast_lock); 1882 1889 1883 1890 return err;