| @@ -72,7 +72,8 @@ __br_multicast_add_group(struct net_bridge *br, · 71 unmodified lines |
| 72 | struct br_ip *group, | 72 | struct br_ip *group, |
| 73 | const unsigned char *src, | 73 | const unsigned char *src, |
| 74 | u8 filter_mode, | 74 | u8 filter_mode, |
| 75 | bool igmpv2_mldv1); | 75 | bool igmpv2_mldv1, |
| | 76 | bool blocked); |
| 76 | static void br_multicast_find_del_pg(struct net_bridge *br, | 77 | static void br_multicast_find_del_pg(struct net_bridge *br, |
| 77 | struct net_bridge_port_group *pg); | 78 | struct net_bridge_port_group *pg); |
| 78 | | 79 | |
| @@ -211,7 +212,7 @@ static void __fwd_add_star_excl(struct net_bridge_port_group *pg, · 132 unmodified lines |
| 211 | return; | 212 | return; |
| 212 | | 213 | |
| 213 | src_pg = __br_multicast_add_group(br, pg->key.port, sg_ip, pg->eth_addr, | 214 | src_pg = __br_multicast_add_group(br, pg->key.port, sg_ip, pg->eth_addr, |
| 214 | MCAST_INCLUDE, false); | 215 | MCAST_INCLUDE, false, false); |
| 215 | if (IS_ERR_OR_NULL(src_pg) || | 216 | if (IS_ERR_OR_NULL(src_pg) || |
| 216 | src_pg->rt_protocol != RTPROT_KERNEL) | 217 | src_pg->rt_protocol != RTPROT_KERNEL) |
| 217 | return; | 218 | return; |
| @@ -343,7 +344,7 @@ void br_multicast_sg_add_exclude_ports(struct net_bridge_mdb_entry *star_mp, · 125 unmodified lines |
| 343 | src_pg = __br_multicast_add_group(br, pg->key.port, | 344 | src_pg = __br_multicast_add_group(br, pg->key.port, |
| 344 | &sg->key.addr, | 345 | &sg->key.addr, |
| 345 | sg->eth_addr, | 346 | sg->eth_addr, |
| 346 | MCAST_INCLUDE, false); | 347 | MCAST_INCLUDE, false, false); |
| 347 | if (IS_ERR_OR_NULL(src_pg) || | 348 | if (IS_ERR_OR_NULL(src_pg) || |
| 348 | src_pg->rt_protocol != RTPROT_KERNEL) | 349 | src_pg->rt_protocol != RTPROT_KERNEL) |
| 349 | continue; | 350 | continue; |
| @@ -364,7 +365,8 @@ static void br_multicast_fwd_src_add(struct net_bridge_group_src *src) · 14 unmodified lines |
| 364 | sg_ip = src->pg->key.addr; | 365 | sg_ip = src->pg->key.addr; |
| 365 | sg_ip.src = src->addr.src; | 366 | sg_ip.src = src->addr.src; |
| 366 | sg = __br_multicast_add_group(src->br, src->pg->key.port, &sg_ip, | 367 | sg = __br_multicast_add_group(src->br, src->pg->key.port, &sg_ip, |
| 367 | src->pg->eth_addr, MCAST_INCLUDE, false); | 368 | src->pg->eth_addr, MCAST_INCLUDE, false, |
| | 369 | !timer_pending(&src->timer)); |
| 368 | if (IS_ERR_OR_NULL(sg)) | 370 | if (IS_ERR_OR_NULL(sg)) |
| 369 | return; | 371 | return; |
| 370 | src->flags |= BR_SGRP_F_INSTALLED; | 372 | src->flags |= BR_SGRP_F_INSTALLED; |
| @@ -415,9 +417,38 @@ static void br_multicast_fwd_src_remove(struct net_bridge_group_src *src) · 44 unmodified lines |
| 415 | src->flags &= ~BR_SGRP_F_INSTALLED; | 417 | src->flags &= ~BR_SGRP_F_INSTALLED; |
| 416 | } | 418 | } |
| 417 | | 419 | |
| | 420 | /* install S,G and based on src's timer enable or disable forwarding */ |
| 418 | static void br_multicast_fwd_src_handle(struct net_bridge_group_src *src) | 421 | static void br_multicast_fwd_src_handle(struct net_bridge_group_src *src) |
| 419 | { | 422 | { |
| | 423 | struct net_bridge_port_group_sg_key sg_key; |
| | 424 | struct net_bridge_port_group *sg; |
| | 425 | u8 old_flags; |
| | 426 | |
| 420 | br_multicast_fwd_src_add(src); | 427 | br_multicast_fwd_src_add(src); |
| | 428 | |
| | 429 | memset(&sg_key, 0, sizeof(sg_key)); |
| | 430 | sg_key.addr = src->pg->key.addr; |
| | 431 | sg_key.addr.src = src->addr.src; |
| | 432 | sg_key.port = src->pg->key.port; |
| | 433 | |
| | 434 | sg = br_sg_port_find(src->br, &sg_key); |
| | 435 | if (!sg || (sg->flags & MDB_PG_FLAGS_PERMANENT)) |
| | 436 | return; |
| | 437 | |
| | 438 | old_flags = sg->flags; |
| | 439 | if (timer_pending(&src->timer)) |
| | 440 | sg->flags &= ~MDB_PG_FLAGS_BLOCKED; |
| | 441 | else |
| | 442 | sg->flags |= MDB_PG_FLAGS_BLOCKED; |
| | 443 | |
| | 444 | if (old_flags != sg->flags) { |
| | 445 | struct net_bridge_mdb_entry *sg_mp; |
| | 446 | |
| | 447 | sg_mp = br_mdb_ip_get(src->br, &sg_key.addr); |
| | 448 | if (!sg_mp) |
| | 449 | return; |
| | 450 | br_mdb_notify(src->br->dev, sg_mp, sg, RTM_NEWMDB); |
| | 451 | } |
| 421 | } | 452 | } |
| 422 | | 453 | |
| 423 | static void br_multicast_destroy_mdb_entry(struct net_bridge_mcast_gc *gc) | 454 | static void br_multicast_destroy_mdb_entry(struct net_bridge_mcast_gc *gc) |
| @@ -995,7 +1026,10 @@ static void br_multicast_group_src_expired(struct timer_list *t) · 571 unmodified lines |
| 995 | if (!hlist_empty(&pg->src_list)) | 1026 | if (!hlist_empty(&pg->src_list)) |
| 996 | goto out; | 1027 | goto out; |
| 997 | br_multicast_find_del_pg(br, pg); | 1028 | br_multicast_find_del_pg(br, pg); |
| | 1029 | } else { |
| | 1030 | br_multicast_fwd_src_handle(src); |
| 998 | } | 1031 | } |
| | 1032 | |
| 999 | out: | 1033 | out: |
| 1000 | spin_unlock(&br->multicast_lock); | 1034 | spin_unlock(&br->multicast_lock); |
| 1001 | } | 1035 | } |
| @@ -1131,7 +1165,8 @@ __br_multicast_add_group(struct net_bridge *br, · 129 unmodified lines |
| 1131 | struct br_ip *group, | 1165 | struct br_ip *group, |
| 1132 | const unsigned char *src, | 1166 | const unsigned char *src, |
| 1133 | u8 filter_mode, | 1167 | u8 filter_mode, |
| 1134 | bool igmpv2_mldv1) | 1168 | bool igmpv2_mldv1, |
| | 1169 | bool blocked) |
| 1135 | { | 1170 | { |
| 1136 | struct net_bridge_port_group __rcu **pp; | 1171 | struct net_bridge_port_group __rcu **pp; |
| 1137 | struct net_bridge_port_group *p = NULL; | 1172 | struct net_bridge_port_group *p = NULL; |
| @@ -1167,6 +1202,8 @@ __br_multicast_add_group(struct net_bridge *br, · 29 unmodified lines |
| 1167 | goto out; | 1202 | goto out; |
| 1168 | } | 1203 | } |
| 1169 | rcu_assign_pointer(*pp, p); | 1204 | rcu_assign_pointer(*pp, p); |
| | 1205 | if (blocked) |
| | 1206 | p->flags |= MDB_PG_FLAGS_BLOCKED; |
| 1170 | br_mdb_notify(br->dev, mp, p, RTM_NEWMDB); | 1207 | br_mdb_notify(br->dev, mp, p, RTM_NEWMDB); |
| 1171 | | 1208 | |
| 1172 | found: | 1209 | found: |
| @@ -1189,7 +1226,7 @@ static int br_multicast_add_group(struct net_bridge *br, · 16 unmodified lines |
| 1189 | | 1226 | |
| 1190 | spin_lock(&br->multicast_lock); | 1227 | spin_lock(&br->multicast_lock); |
| 1191 | pg = __br_multicast_add_group(br, port, group, src, filter_mode, | 1228 | pg = __br_multicast_add_group(br, port, group, src, filter_mode, |
| 1192 | igmpv2_mldv1); | 1229 | igmpv2_mldv1, false); |
| 1193 | /* NULL is considered valid for host joined groups */ | 1230 | /* NULL is considered valid for host joined groups */ |
| 1194 | err = IS_ERR(pg) ? PTR_ERR(pg) : 0; | 1231 | err = IS_ERR(pg) ? PTR_ERR(pg) : 0; |
| 1195 | spin_unlock(&br->multicast_lock); | 1232 | spin_unlock(&br->multicast_lock); |