645-bridge_multicast_to_unicast.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  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 = eth_hdr(skb)->h_source;
  95. struct igmpv3_report *ih;
  96. struct igmpv3_grec *grec;
  97. int i;
  98. @@ -1008,7 +1031,7 @@ static int br_ip4_multicast_igmp3_report
  99. continue;
  100. }
  101. - err = br_ip4_multicast_add_group(br, port, group, vid);
  102. + err = br_ip4_multicast_add_group(br, port, group, vid, src);
  103. if (err)
  104. break;
  105. }
  106. @@ -1022,6 +1045,7 @@ static int br_ip6_multicast_mld2_report(
  107. struct sk_buff *skb,
  108. u16 vid)
  109. {
  110. + const unsigned char *src = eth_hdr(skb)->h_source;
  111. struct icmp6hdr *icmp6h;
  112. struct mld2_grec *grec;
  113. int i;
  114. @@ -1070,7 +1094,7 @@ static int br_ip6_multicast_mld2_report(
  115. }
  116. err = br_ip6_multicast_add_group(br, port, &grec->grec_mca,
  117. - vid);
  118. + vid, src);
  119. if (!err)
  120. break;
  121. }
  122. @@ -1407,7 +1431,8 @@ br_multicast_leave_group(struct net_brid
  123. struct net_bridge_port *port,
  124. struct br_ip *group,
  125. struct bridge_mcast_other_query *other_query,
  126. - struct bridge_mcast_own_query *own_query)
  127. + struct bridge_mcast_own_query *own_query,
  128. + const unsigned char *src)
  129. {
  130. struct net_bridge_mdb_htable *mdb;
  131. struct net_bridge_mdb_entry *mp;
  132. @@ -1457,7 +1482,7 @@ br_multicast_leave_group(struct net_brid
  133. for (pp = &mp->ports;
  134. (p = mlock_dereference(*pp, br)) != NULL;
  135. pp = &p->next) {
  136. - if (p->port != port)
  137. + if (!br_port_group_equal(p, port, src))
  138. continue;
  139. rcu_assign_pointer(*pp, p->next);
  140. @@ -1491,7 +1516,7 @@ br_multicast_leave_group(struct net_brid
  141. for (p = mlock_dereference(mp->ports, br);
  142. p != NULL;
  143. p = mlock_dereference(p->next, br)) {
  144. - if (p->port != port)
  145. + if (!br_port_group_equal(p, port, src))
  146. continue;
  147. if (!hlist_unhashed(&p->mglist) &&
  148. @@ -1509,8 +1534,8 @@ out:
  149. static void br_ip4_multicast_leave_group(struct net_bridge *br,
  150. struct net_bridge_port *port,
  151. - __be32 group,
  152. - __u16 vid)
  153. + __be32 group, __u16 vid,
  154. + const unsigned char *src)
  155. {
  156. struct br_ip br_group;
  157. struct bridge_mcast_own_query *own_query;
  158. @@ -1525,14 +1550,14 @@ static void br_ip4_multicast_leave_group
  159. br_group.vid = vid;
  160. br_multicast_leave_group(br, port, &br_group, &br->ip4_other_query,
  161. - own_query);
  162. + own_query, src);
  163. }
  164. #if IS_ENABLED(CONFIG_IPV6)
  165. static void br_ip6_multicast_leave_group(struct net_bridge *br,
  166. struct net_bridge_port *port,
  167. const struct in6_addr *group,
  168. - __u16 vid)
  169. + __u16 vid, const unsigned char *src)
  170. {
  171. struct br_ip br_group;
  172. struct bridge_mcast_own_query *own_query;
  173. @@ -1547,7 +1572,7 @@ static void br_ip6_multicast_leave_group
  174. br_group.vid = vid;
  175. br_multicast_leave_group(br, port, &br_group, &br->ip6_other_query,
  176. - own_query);
  177. + own_query, src);
  178. }
  179. #endif
  180. @@ -1556,6 +1581,7 @@ static int br_multicast_ipv4_rcv(struct
  181. struct sk_buff *skb,
  182. u16 vid)
  183. {
  184. + const unsigned char *src = eth_hdr(skb)->h_source;
  185. struct sk_buff *skb2 = skb;
  186. const struct iphdr *iph;
  187. struct igmphdr *ih;
  188. @@ -1629,7 +1655,7 @@ static int br_multicast_ipv4_rcv(struct
  189. case IGMP_HOST_MEMBERSHIP_REPORT:
  190. case IGMPV2_HOST_MEMBERSHIP_REPORT:
  191. BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
  192. - err = br_ip4_multicast_add_group(br, port, ih->group, vid);
  193. + err = br_ip4_multicast_add_group(br, port, ih->group, vid, src);
  194. break;
  195. case IGMPV3_HOST_MEMBERSHIP_REPORT:
  196. err = br_ip4_multicast_igmp3_report(br, port, skb2, vid);
  197. @@ -1638,7 +1664,7 @@ static int br_multicast_ipv4_rcv(struct
  198. err = br_ip4_multicast_query(br, port, skb2, vid);
  199. break;
  200. case IGMP_HOST_LEAVE_MESSAGE:
  201. - br_ip4_multicast_leave_group(br, port, ih->group, vid);
  202. + br_ip4_multicast_leave_group(br, port, ih->group, vid, src);
  203. break;
  204. }
  205. @@ -1656,6 +1682,7 @@ static int br_multicast_ipv6_rcv(struct
  206. struct sk_buff *skb,
  207. u16 vid)
  208. {
  209. + const unsigned char *src = eth_hdr(skb)->h_source;
  210. struct sk_buff *skb2;
  211. const struct ipv6hdr *ip6h;
  212. u8 icmp6_type;
  213. @@ -1765,7 +1792,8 @@ static int br_multicast_ipv6_rcv(struct
  214. }
  215. mld = (struct mld_msg *)skb_transport_header(skb2);
  216. BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
  217. - err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, vid);
  218. + err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, vid,
  219. + src);
  220. break;
  221. }
  222. case ICMPV6_MLD2_REPORT:
  223. @@ -1782,7 +1810,7 @@ static int br_multicast_ipv6_rcv(struct
  224. goto out;
  225. }
  226. mld = (struct mld_msg *)skb_transport_header(skb2);
  227. - br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid);
  228. + br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid, src);
  229. }
  230. }
  231. --- a/net/bridge/br_private.h
  232. +++ b/net/bridge/br_private.h
  233. @@ -112,6 +112,9 @@ struct net_bridge_port_group {
  234. struct timer_list timer;
  235. struct br_ip addr;
  236. unsigned char state;
  237. +
  238. + unsigned char eth_addr[ETH_ALEN];
  239. + bool unicast;
  240. };
  241. struct net_bridge_mdb_entry
  242. @@ -173,6 +176,7 @@ struct net_bridge_port
  243. #define BR_AUTO_MASK (BR_FLOOD | BR_LEARNING)
  244. #define BR_PROMISC 0x00000080
  245. #define BR_ISOLATE_MODE 0x00000100
  246. +#define BR_MULTICAST_TO_UCAST 0x00000200
  247. #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  248. struct bridge_mcast_own_query ip4_own_query;
  249. @@ -485,7 +489,8 @@ void br_multicast_free_pg(struct rcu_hea
  250. struct net_bridge_port_group *
  251. br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group,
  252. struct net_bridge_port_group __rcu *next,
  253. - unsigned char state);
  254. + unsigned char state,
  255. + const unsigned char *src);
  256. void br_mdb_init(void);
  257. void br_mdb_uninit(void);
  258. void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
  259. --- a/net/bridge/br_mdb.c
  260. +++ b/net/bridge/br_mdb.c
  261. @@ -342,7 +342,7 @@ static int br_mdb_add_group(struct net_b
  262. break;
  263. }
  264. - p = br_multicast_new_port_group(port, group, *pp, state);
  265. + p = br_multicast_new_port_group(port, group, *pp, state, NULL);
  266. if (unlikely(!p))
  267. return -ENOMEM;
  268. rcu_assign_pointer(*pp, p);
  269. --- a/net/bridge/br_forward.c
  270. +++ b/net/bridge/br_forward.c
  271. @@ -168,6 +168,29 @@ out:
  272. return p;
  273. }
  274. +static struct net_bridge_port *maybe_deliver_addr(
  275. + struct net_bridge_port *prev, struct net_bridge_port *p,
  276. + struct sk_buff *skb, const unsigned char *addr,
  277. + void (*__packet_hook)(const struct net_bridge_port *p,
  278. + struct sk_buff *skb))
  279. +{
  280. + struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
  281. +
  282. + if (!should_deliver(p, skb))
  283. + return prev;
  284. +
  285. + skb = skb_copy(skb, GFP_ATOMIC);
  286. + if (!skb) {
  287. + dev->stats.tx_dropped++;
  288. + return prev;
  289. + }
  290. +
  291. + memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN);
  292. + __packet_hook(p, skb);
  293. +
  294. + return prev;
  295. +}
  296. +
  297. /* called under bridge lock */
  298. static void br_flood(struct net_bridge *br, struct sk_buff *skb,
  299. struct sk_buff *skb0,
  300. @@ -232,6 +255,7 @@ static void br_multicast_flood(struct ne
  301. struct net_bridge_port *prev = NULL;
  302. struct net_bridge_port_group *p;
  303. struct hlist_node *rp;
  304. + const unsigned char *addr;
  305. rp = rcu_dereference(hlist_first_rcu(&br->router_list));
  306. p = mdst ? rcu_dereference(mdst->ports) : NULL;
  307. @@ -242,10 +266,19 @@ static void br_multicast_flood(struct ne
  308. rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
  309. NULL;
  310. - port = (unsigned long)lport > (unsigned long)rport ?
  311. - lport : rport;
  312. -
  313. - prev = maybe_deliver(prev, port, skb, __packet_hook);
  314. + if ((unsigned long)lport > (unsigned long)rport) {
  315. + port = lport;
  316. + addr = p->unicast ? p->eth_addr : NULL;
  317. + } else {
  318. + port = rport;
  319. + addr = NULL;
  320. + }
  321. +
  322. + if (addr)
  323. + prev = maybe_deliver_addr(prev, port, skb, addr,
  324. + __packet_hook);
  325. + else
  326. + prev = maybe_deliver(prev, port, skb, __packet_hook);
  327. if (IS_ERR(prev))
  328. goto out;
  329. --- a/net/bridge/br_sysfs_if.c
  330. +++ b/net/bridge/br_sysfs_if.c
  331. @@ -202,6 +202,7 @@ static BRPORT_ATTR(multicast_router, S_I
  332. store_multicast_router);
  333. BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE);
  334. +BRPORT_ATTR_FLAG(multicast_to_unicast, BR_MULTICAST_TO_UCAST);
  335. #endif
  336. static const struct brport_attribute *brport_attrs[] = {
  337. @@ -228,6 +229,7 @@ static const struct brport_attribute *br
  338. #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
  339. &brport_attr_multicast_router,
  340. &brport_attr_multicast_fast_leave,
  341. + &brport_attr_multicast_to_unicast,
  342. #endif
  343. &brport_attr_isolate_mode,
  344. NULL