645-bridge_multicast_to_unicast.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. --- a/net/bridge/br_multicast.c
  2. +++ b/net/bridge/br_multicast.c
  3. @@ -635,7 +635,8 @@ struct net_bridge_port_group *br_multica
  4. struct net_bridge_port *port,
  5. struct br_ip *group,
  6. struct net_bridge_port_group __rcu *next,
  7. - unsigned char state)
  8. + unsigned char state,
  9. + const unsigned char *src)
  10. {
  11. struct net_bridge_port_group *p;
  12. @@ -650,12 +651,33 @@ struct net_bridge_port_group *br_multica
  13. hlist_add_head(&p->mglist, &port->mglist);
  14. setup_timer(&p->timer, br_multicast_port_group_expired,
  15. (unsigned long)p);
  16. + if ((port->flags & BR_MULTICAST_TO_UCAST) && src) {
  17. + memcpy(p->eth_addr, src, ETH_ALEN);
  18. + p->unicast = true;
  19. + }
  20. return p;
  21. }
  22. +static bool br_port_group_equal(struct net_bridge_port_group *p,
  23. + struct net_bridge_port *port,
  24. + const unsigned char *src)
  25. +{
  26. + if (p->port != port)
  27. + return false;
  28. +
  29. + if (!p->unicast)
  30. + return true;
  31. +
  32. + if (!src)
  33. + return false;
  34. +
  35. + return ether_addr_equal(src, p->eth_addr);
  36. +}
  37. +
  38. static int br_multicast_add_group(struct net_bridge *br,
  39. struct net_bridge_port *port,
  40. - struct br_ip *group)
  41. + struct br_ip *group,
  42. + const unsigned char *src)
  43. {
  44. struct net_bridge_mdb_entry *mp;
  45. struct net_bridge_port_group *p;
  46. @@ -682,13 +704,13 @@ static int br_multicast_add_group(struct
  47. for (pp = &mp->ports;
  48. (p = mlock_dereference(*pp, br)) != NULL;
  49. pp = &p->next) {
  50. - if (p->port == port)
  51. + if (br_port_group_equal(p, port, src))
  52. goto found;
  53. if ((unsigned long)p->port < (unsigned long)port)
  54. break;
  55. }
  56. - p = br_multicast_new_port_group(port, group, *pp, MDB_TEMPORARY);
  57. + p = br_multicast_new_port_group(port, group, *pp, MDB_TEMPORARY, src);
  58. if (unlikely(!p))
  59. goto err;
  60. rcu_assign_pointer(*pp, p);
  61. @@ -707,7 +729,7 @@ err:
  62. static int br_ip4_multicast_add_group(struct net_bridge *br,
  63. struct net_bridge_port *port,
  64. __be32 group,
  65. - __u16 vid)
  66. + __u16 vid, const unsigned char *src)
  67. {
  68. struct br_ip br_group;
  69. @@ -718,14 +740,14 @@ static int br_ip4_multicast_add_group(st
  70. br_group.proto = htons(ETH_P_IP);
  71. br_group.vid = vid;
  72. - return br_multicast_add_group(br, port, &br_group);
  73. + return br_multicast_add_group(br, port, &br_group, src);
  74. }
  75. #if IS_ENABLED(CONFIG_IPV6)
  76. static int br_ip6_multicast_add_group(struct net_bridge *br,
  77. struct net_bridge_port *port,
  78. const struct in6_addr *group,
  79. - __u16 vid)
  80. + __u16 vid, const unsigned char *src)
  81. {
  82. struct br_ip br_group;
  83. @@ -736,7 +758,7 @@ static int br_ip6_multicast_add_group(st
  84. br_group.proto = htons(ETH_P_IPV6);
  85. br_group.vid = vid;
  86. - return br_multicast_add_group(br, port, &br_group);
  87. + return br_multicast_add_group(br, port, &br_group, src);
  88. }
  89. #endif
  90. @@ -965,6 +987,7 @@ static int br_ip4_multicast_igmp3_report
  91. struct sk_buff *skb,
  92. u16 vid)
  93. {
  94. + const unsigned char *src;
  95. struct igmpv3_report *ih;
  96. struct igmpv3_grec *grec;
  97. int i;
  98. @@ -1008,7 +1031,8 @@ static int br_ip4_multicast_igmp3_report
  99. continue;
  100. }
  101. - err = br_ip4_multicast_add_group(br, port, group, vid);
  102. + src = eth_hdr(skb)->h_source;
  103. + err = br_ip4_multicast_add_group(br, port, group, vid, src);
  104. if (err)
  105. break;
  106. }
  107. @@ -1022,6 +1046,7 @@ static int br_ip6_multicast_mld2_report(
  108. struct sk_buff *skb,
  109. u16 vid)
  110. {
  111. + const unsigned char *src;
  112. struct icmp6hdr *icmp6h;
  113. struct mld2_grec *grec;
  114. int i;
  115. @@ -1069,8 +1094,9 @@ static int br_ip6_multicast_mld2_report(
  116. continue;
  117. }
  118. + src = eth_hdr(skb)->h_source;
  119. err = br_ip6_multicast_add_group(br, port, &grec->grec_mca,
  120. - vid);
  121. + vid, src);
  122. if (err)
  123. break;
  124. }
  125. @@ -1406,7 +1432,8 @@ br_multicast_leave_group(struct net_brid
  126. struct net_bridge_port *port,
  127. struct br_ip *group,
  128. struct bridge_mcast_other_query *other_query,
  129. - struct bridge_mcast_own_query *own_query)
  130. + struct bridge_mcast_own_query *own_query,
  131. + const unsigned char *src)
  132. {
  133. struct net_bridge_mdb_htable *mdb;
  134. struct net_bridge_mdb_entry *mp;
  135. @@ -1456,7 +1483,7 @@ br_multicast_leave_group(struct net_brid
  136. for (pp = &mp->ports;
  137. (p = mlock_dereference(*pp, br)) != NULL;
  138. pp = &p->next) {
  139. - if (p->port != port)
  140. + if (!br_port_group_equal(p, port, src))
  141. continue;
  142. rcu_assign_pointer(*pp, p->next);
  143. @@ -1490,7 +1517,7 @@ br_multicast_leave_group(struct net_brid
  144. for (p = mlock_dereference(mp->ports, br);
  145. p != NULL;
  146. p = mlock_dereference(p->next, br)) {
  147. - if (p->port != port)
  148. + if (!br_port_group_equal(p, port, src))
  149. continue;
  150. if (!hlist_unhashed(&p->mglist) &&
  151. @@ -1508,8 +1535,8 @@ out:
  152. static void br_ip4_multicast_leave_group(struct net_bridge *br,
  153. struct net_bridge_port *port,
  154. - __be32 group,
  155. - __u16 vid)
  156. + __be32 group, __u16 vid,
  157. + const unsigned char *src)
  158. {
  159. struct br_ip br_group;
  160. struct bridge_mcast_own_query *own_query;
  161. @@ -1524,14 +1551,14 @@ static void br_ip4_multicast_leave_group
  162. br_group.vid = vid;
  163. br_multicast_leave_group(br, port, &br_group, &br->ip4_other_query,
  164. - own_query);
  165. + own_query, src);
  166. }
  167. #if IS_ENABLED(CONFIG_IPV6)
  168. static void br_ip6_multicast_leave_group(struct net_bridge *br,
  169. struct net_bridge_port *port,
  170. const struct in6_addr *group,
  171. - __u16 vid)
  172. + __u16 vid, const unsigned char *src)
  173. {
  174. struct br_ip br_group;
  175. struct bridge_mcast_own_query *own_query;
  176. @@ -1546,7 +1573,7 @@ static void br_ip6_multicast_leave_group
  177. br_group.vid = vid;
  178. br_multicast_leave_group(br, port, &br_group, &br->ip6_other_query,
  179. - own_query);
  180. + own_query, src);
  181. }
  182. #endif
  183. @@ -1555,6 +1582,7 @@ static int br_multicast_ipv4_rcv(struct
  184. struct sk_buff *skb,
  185. u16 vid)
  186. {
  187. + const unsigned char *src;
  188. struct sk_buff *skb2 = skb;
  189. const struct iphdr *iph;
  190. struct igmphdr *ih;
  191. @@ -1628,7 +1656,8 @@ static int br_multicast_ipv4_rcv(struct
  192. case IGMP_HOST_MEMBERSHIP_REPORT:
  193. case IGMPV2_HOST_MEMBERSHIP_REPORT:
  194. BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
  195. - err = br_ip4_multicast_add_group(br, port, ih->group, vid);
  196. + src = eth_hdr(skb)->h_source;
  197. + err = br_ip4_multicast_add_group(br, port, ih->group, vid, src);
  198. break;
  199. case IGMPV3_HOST_MEMBERSHIP_REPORT:
  200. err = br_ip4_multicast_igmp3_report(br, port, skb2, vid);
  201. @@ -1637,7 +1666,8 @@ static int br_multicast_ipv4_rcv(struct
  202. err = br_ip4_multicast_query(br, port, skb2, vid);
  203. break;
  204. case IGMP_HOST_LEAVE_MESSAGE:
  205. - br_ip4_multicast_leave_group(br, port, ih->group, vid);
  206. + src = eth_hdr(skb)->h_source;
  207. + br_ip4_multicast_leave_group(br, port, ih->group, vid, src);
  208. break;
  209. }
  210. @@ -1655,6 +1685,7 @@ static int br_multicast_ipv6_rcv(struct
  211. struct sk_buff *skb,
  212. u16 vid)
  213. {
  214. + const unsigned char *src;
  215. struct sk_buff *skb2;
  216. const struct ipv6hdr *ip6h;
  217. u8 icmp6_type;
  218. @@ -1764,7 +1795,9 @@ static int br_multicast_ipv6_rcv(struct
  219. }
  220. mld = (struct mld_msg *)skb_transport_header(skb2);
  221. BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
  222. - err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, vid);
  223. + src = eth_hdr(skb)->h_source;
  224. + err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, vid,
  225. + src);
  226. break;
  227. }
  228. case ICMPV6_MLD2_REPORT:
  229. @@ -1781,7 +1814,8 @@ static int br_multicast_ipv6_rcv(struct
  230. goto out;
  231. }
  232. mld = (struct mld_msg *)skb_transport_header(skb2);
  233. - br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid);
  234. + src = eth_hdr(skb)->h_source;
  235. + br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid, src);
  236. }
  237. }
  238. --- a/net/bridge/br_private.h
  239. +++ b/net/bridge/br_private.h
  240. @@ -112,6 +112,9 @@ struct net_bridge_port_group {
  241. struct timer_list timer;
  242. struct br_ip addr;
  243. unsigned char state;
  244. +
  245. + unsigned char eth_addr[ETH_ALEN];
  246. + bool unicast;
  247. };
  248. struct net_bridge_mdb_entry
  249. @@ -173,6 +176,7 @@ struct net_bridge_port
  250. #define BR_AUTO_MASK (BR_FLOOD | BR_LEARNING)
  251. #define BR_PROMISC 0x00000080
  252. #define BR_ISOLATE_MODE 0x00000100
  253. +#define BR_MULTICAST_TO_UCAST 0x00000200
  254. #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  255. struct bridge_mcast_own_query ip4_own_query;
  256. @@ -485,7 +489,8 @@ void br_multicast_free_pg(struct rcu_hea
  257. struct net_bridge_port_group *
  258. br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group,
  259. struct net_bridge_port_group __rcu *next,
  260. - unsigned char state);
  261. + unsigned char state,
  262. + const unsigned char *src);
  263. void br_mdb_init(void);
  264. void br_mdb_uninit(void);
  265. void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
  266. --- a/net/bridge/br_mdb.c
  267. +++ b/net/bridge/br_mdb.c
  268. @@ -342,7 +342,7 @@ static int br_mdb_add_group(struct net_b
  269. break;
  270. }
  271. - p = br_multicast_new_port_group(port, group, *pp, state);
  272. + p = br_multicast_new_port_group(port, group, *pp, state, NULL);
  273. if (unlikely(!p))
  274. return -ENOMEM;
  275. rcu_assign_pointer(*pp, p);
  276. --- a/net/bridge/br_forward.c
  277. +++ b/net/bridge/br_forward.c
  278. @@ -168,6 +168,34 @@ out:
  279. return p;
  280. }
  281. +static struct net_bridge_port *maybe_deliver_addr(
  282. + struct net_bridge_port *prev, struct net_bridge_port *p,
  283. + struct sk_buff *skb, const unsigned char *addr,
  284. + void (*__packet_hook)(const struct net_bridge_port *p,
  285. + struct sk_buff *skb))
  286. +{
  287. + struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
  288. + const unsigned char *src = eth_hdr(skb)->h_source;
  289. +
  290. + if (!should_deliver(p, skb))
  291. + return prev;
  292. +
  293. + /* Even with hairpin, no soliloquies - prevent breaking IPv6 DAD */
  294. + if (skb->dev == p->dev && ether_addr_equal(src, addr))
  295. + return prev;
  296. +
  297. + skb = skb_copy(skb, GFP_ATOMIC);
  298. + if (!skb) {
  299. + dev->stats.tx_dropped++;
  300. + return prev;
  301. + }
  302. +
  303. + memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN);
  304. + __packet_hook(p, skb);
  305. +
  306. + return prev;
  307. +}
  308. +
  309. /* called under bridge lock */
  310. static void br_flood(struct net_bridge *br, struct sk_buff *skb,
  311. struct sk_buff *skb0,
  312. @@ -232,6 +260,7 @@ static void br_multicast_flood(struct ne
  313. struct net_bridge_port *prev = NULL;
  314. struct net_bridge_port_group *p;
  315. struct hlist_node *rp;
  316. + const unsigned char *addr;
  317. rp = rcu_dereference(hlist_first_rcu(&br->router_list));
  318. p = mdst ? rcu_dereference(mdst->ports) : NULL;
  319. @@ -242,10 +271,19 @@ static void br_multicast_flood(struct ne
  320. rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
  321. NULL;
  322. - port = (unsigned long)lport > (unsigned long)rport ?
  323. - lport : rport;
  324. -
  325. - prev = maybe_deliver(prev, port, skb, __packet_hook);
  326. + if ((unsigned long)lport > (unsigned long)rport) {
  327. + port = lport;
  328. + addr = p->unicast ? p->eth_addr : NULL;
  329. + } else {
  330. + port = rport;
  331. + addr = NULL;
  332. + }
  333. +
  334. + if (addr)
  335. + prev = maybe_deliver_addr(prev, port, skb, addr,
  336. + __packet_hook);
  337. + else
  338. + prev = maybe_deliver(prev, port, skb, __packet_hook);
  339. if (IS_ERR(prev))
  340. goto out;
  341. --- a/net/bridge/br_sysfs_if.c
  342. +++ b/net/bridge/br_sysfs_if.c
  343. @@ -202,6 +202,7 @@ static BRPORT_ATTR(multicast_router, S_I
  344. store_multicast_router);
  345. BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE);
  346. +BRPORT_ATTR_FLAG(multicast_to_unicast, BR_MULTICAST_TO_UCAST);
  347. #endif
  348. static const struct brport_attribute *brport_attrs[] = {
  349. @@ -228,6 +229,7 @@ static const struct brport_attribute *br
  350. #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  351. &brport_attr_multicast_router,
  352. &brport_attr_multicast_fast_leave,
  353. + &brport_attr_multicast_to_unicast,
  354. #endif
  355. &brport_attr_isolate_mode,
  356. NULL