br_multicast.c (0436862e417e8c68e7b85ebf66ffca9d54c43e9a) | br_multicast.c (e6231bca6a27dcc718e258b71bad42977ca3344e) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Bridge multicast support. 4 * 5 * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au> 6 */ 7 8#include <linux/err.h> --- 1215 unchanged lines hidden (view full) --- 1224 del_timer(&port->multicast_router_timer); 1225 del_timer(&port->ip4_own_query.timer); 1226#if IS_ENABLED(CONFIG_IPV6) 1227 del_timer(&port->ip6_own_query.timer); 1228#endif 1229 spin_unlock(&br->multicast_lock); 1230} 1231 | 1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Bridge multicast support. 4 * 5 * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au> 6 */ 7 8#include <linux/err.h> --- 1215 unchanged lines hidden (view full) --- 1224 del_timer(&port->multicast_router_timer); 1225 del_timer(&port->ip4_own_query.timer); 1226#if IS_ENABLED(CONFIG_IPV6) 1227 del_timer(&port->ip6_own_query.timer); 1228#endif 1229 spin_unlock(&br->multicast_lock); 1230} 1231 |
1232static int __grp_src_delete_marked(struct net_bridge_port_group *pg) 1233{ 1234 struct net_bridge_group_src *ent; 1235 struct hlist_node *tmp; 1236 int deleted = 0; 1237 1238 hlist_for_each_entry_safe(ent, tmp, &pg->src_list, node) 1239 if (ent->flags & BR_SGRP_F_DELETE) { 1240 br_multicast_del_group_src(ent); 1241 deleted++; 1242 } 1243 1244 return deleted; 1245} 1246 |
|
1232/* State Msg type New state Actions 1233 * INCLUDE (A) IS_IN (B) INCLUDE (A+B) (B)=GMI 1234 * INCLUDE (A) ALLOW (B) INCLUDE (A+B) (B)=GMI 1235 * EXCLUDE (X,Y) ALLOW (A) EXCLUDE (X+A,Y-A) (A)=GMI 1236 */ 1237static bool br_multicast_isinc_allow(struct net_bridge_port_group *pg, 1238 void *srcs, u32 nsrcs, size_t src_size) 1239{ --- 18 unchanged lines hidden (view full) --- 1258 if (ent) 1259 mod_timer(&ent->timer, now + br_multicast_gmi(br)); 1260 srcs += src_size; 1261 } 1262 1263 return changed; 1264} 1265 | 1247/* State Msg type New state Actions 1248 * INCLUDE (A) IS_IN (B) INCLUDE (A+B) (B)=GMI 1249 * INCLUDE (A) ALLOW (B) INCLUDE (A+B) (B)=GMI 1250 * EXCLUDE (X,Y) ALLOW (A) EXCLUDE (X+A,Y-A) (A)=GMI 1251 */ 1252static bool br_multicast_isinc_allow(struct net_bridge_port_group *pg, 1253 void *srcs, u32 nsrcs, size_t src_size) 1254{ --- 18 unchanged lines hidden (view full) --- 1273 if (ent) 1274 mod_timer(&ent->timer, now + br_multicast_gmi(br)); 1275 srcs += src_size; 1276 } 1277 1278 return changed; 1279} 1280 |
1281/* State Msg type New state Actions 1282 * INCLUDE (A) IS_EX (B) EXCLUDE (A*B,B-A) (B-A)=0 1283 * Delete (A-B) 1284 * Group Timer=GMI 1285 */ 1286static void __grp_src_isexc_incl(struct net_bridge_port_group *pg, 1287 void *srcs, u32 nsrcs, size_t src_size) 1288{ 1289 struct net_bridge_group_src *ent; 1290 struct br_ip src_ip; 1291 u32 src_idx; 1292 1293 hlist_for_each_entry(ent, &pg->src_list, node) 1294 ent->flags |= BR_SGRP_F_DELETE; 1295 1296 memset(&src_ip, 0, sizeof(src_ip)); 1297 src_ip.proto = pg->addr.proto; 1298 for (src_idx = 0; src_idx < nsrcs; src_idx++) { 1299 memcpy(&src_ip.u, srcs, src_size); 1300 ent = br_multicast_find_group_src(pg, &src_ip); 1301 if (ent) 1302 ent->flags &= ~BR_SGRP_F_DELETE; 1303 else 1304 br_multicast_new_group_src(pg, &src_ip); 1305 srcs += src_size; 1306 } 1307 1308 __grp_src_delete_marked(pg); 1309} 1310 1311/* State Msg type New state Actions 1312 * EXCLUDE (X,Y) IS_EX (A) EXCLUDE (A-Y,Y*A) (A-X-Y)=GMI 1313 * Delete (X-A) 1314 * Delete (Y-A) 1315 * Group Timer=GMI 1316 */ 1317static bool __grp_src_isexc_excl(struct net_bridge_port_group *pg, 1318 void *srcs, u32 nsrcs, size_t src_size) 1319{ 1320 struct net_bridge *br = pg->port->br; 1321 struct net_bridge_group_src *ent; 1322 unsigned long now = jiffies; 1323 bool changed = false; 1324 struct br_ip src_ip; 1325 u32 src_idx; 1326 1327 hlist_for_each_entry(ent, &pg->src_list, node) 1328 ent->flags |= BR_SGRP_F_DELETE; 1329 1330 memset(&src_ip, 0, sizeof(src_ip)); 1331 src_ip.proto = pg->addr.proto; 1332 for (src_idx = 0; src_idx < nsrcs; src_idx++) { 1333 memcpy(&src_ip.u, srcs, src_size); 1334 ent = br_multicast_find_group_src(pg, &src_ip); 1335 if (ent) { 1336 ent->flags &= ~BR_SGRP_F_DELETE; 1337 } else { 1338 ent = br_multicast_new_group_src(pg, &src_ip); 1339 if (ent) { 1340 mod_timer(&ent->timer, 1341 now + br_multicast_gmi(br)); 1342 changed = true; 1343 } 1344 } 1345 srcs += src_size; 1346 } 1347 1348 if (__grp_src_delete_marked(pg)) 1349 changed = true; 1350 1351 return changed; 1352} 1353 1354static bool br_multicast_isexc(struct net_bridge_port_group *pg, 1355 void *srcs, u32 nsrcs, size_t src_size) 1356{ 1357 struct net_bridge *br = pg->port->br; 1358 bool changed = false; 1359 1360 switch (pg->filter_mode) { 1361 case MCAST_INCLUDE: 1362 __grp_src_isexc_incl(pg, srcs, nsrcs, src_size); 1363 changed = true; 1364 break; 1365 case MCAST_EXCLUDE: 1366 changed = __grp_src_isexc_excl(pg, srcs, nsrcs, src_size); 1367 break; 1368 } 1369 1370 pg->filter_mode = MCAST_EXCLUDE; 1371 mod_timer(&pg->timer, jiffies + br_multicast_gmi(br)); 1372 1373 return changed; 1374} 1375 |
|
1266static struct net_bridge_port_group * 1267br_multicast_find_port(struct net_bridge_mdb_entry *mp, 1268 struct net_bridge_port *p, 1269 const unsigned char *src) 1270{ 1271 struct net_bridge_port_group *pg; 1272 struct net_bridge *br = mp->br; 1273 --- 81 unchanged lines hidden (view full) --- 1355 goto unlock_continue; 1356 /* reload grec */ 1357 grec = (void *)(skb->data + len - sizeof(*grec) - (nsrcs * 4)); 1358 switch (type) { 1359 case IGMPV3_ALLOW_NEW_SOURCES: 1360 changed = br_multicast_isinc_allow(pg, grec->grec_src, 1361 nsrcs, sizeof(__be32)); 1362 break; | 1376static struct net_bridge_port_group * 1377br_multicast_find_port(struct net_bridge_mdb_entry *mp, 1378 struct net_bridge_port *p, 1379 const unsigned char *src) 1380{ 1381 struct net_bridge_port_group *pg; 1382 struct net_bridge *br = mp->br; 1383 --- 81 unchanged lines hidden (view full) --- 1465 goto unlock_continue; 1466 /* reload grec */ 1467 grec = (void *)(skb->data + len - sizeof(*grec) - (nsrcs * 4)); 1468 switch (type) { 1469 case IGMPV3_ALLOW_NEW_SOURCES: 1470 changed = br_multicast_isinc_allow(pg, grec->grec_src, 1471 nsrcs, sizeof(__be32)); 1472 break; |
1473 case IGMPV3_MODE_IS_INCLUDE: 1474 changed = br_multicast_isinc_allow(pg, grec->grec_src, nsrcs, 1475 sizeof(__be32)); 1476 break; 1477 case IGMPV3_MODE_IS_EXCLUDE: 1478 changed = br_multicast_isexc(pg, grec->grec_src, nsrcs, 1479 sizeof(__be32)); 1480 break; |
|
1363 } 1364 if (changed) 1365 br_mdb_notify(br->dev, mdst, pg, RTM_NEWMDB); 1366unlock_continue: 1367 spin_unlock_bh(&br->multicast_lock); 1368 } 1369 1370 return err; --- 90 unchanged lines hidden (view full) --- 1461 if (!pg || (pg->flags & MDB_PG_FLAGS_PERMANENT)) 1462 goto unlock_continue; 1463 switch (grec->grec_type) { 1464 case MLD2_ALLOW_NEW_SOURCES: 1465 changed = br_multicast_isinc_allow(pg, grec->grec_src, 1466 nsrcs, 1467 sizeof(struct in6_addr)); 1468 break; | 1481 } 1482 if (changed) 1483 br_mdb_notify(br->dev, mdst, pg, RTM_NEWMDB); 1484unlock_continue: 1485 spin_unlock_bh(&br->multicast_lock); 1486 } 1487 1488 return err; --- 90 unchanged lines hidden (view full) --- 1579 if (!pg || (pg->flags & MDB_PG_FLAGS_PERMANENT)) 1580 goto unlock_continue; 1581 switch (grec->grec_type) { 1582 case MLD2_ALLOW_NEW_SOURCES: 1583 changed = br_multicast_isinc_allow(pg, grec->grec_src, 1584 nsrcs, 1585 sizeof(struct in6_addr)); 1586 break; |
1587 case MLD2_MODE_IS_INCLUDE: 1588 changed = br_multicast_isinc_allow(pg, grec->grec_src, nsrcs, 1589 sizeof(struct in6_addr)); 1590 break; 1591 case MLD2_MODE_IS_EXCLUDE: 1592 changed = br_multicast_isexc(pg, grec->grec_src, nsrcs, 1593 sizeof(struct in6_addr)); 1594 break; |
|
1469 } 1470 if (changed) 1471 br_mdb_notify(br->dev, mdst, pg, RTM_NEWMDB); 1472unlock_continue: 1473 spin_unlock_bh(&br->multicast_lock); 1474 } 1475 1476 return err; --- 1447 unchanged lines hidden --- | 1595 } 1596 if (changed) 1597 br_mdb_notify(br->dev, mdst, pg, RTM_NEWMDB); 1598unlock_continue: 1599 spin_unlock_bh(&br->multicast_lock); 1600 } 1601 1602 return err; --- 1447 unchanged lines hidden --- |