@@ -1252,3 +1252,207 @@ async def test_bridge_pool_range_limited(dbus, sysnet, nursery):
12521252
12531253 res = await mctpd .stop_mctpd ()
12541254 assert res == 0
1255+
1256+ """ Test that we use endpoint poll interval from the config and
1257+ that we discover bridged endpoints via polling"""
1258+ async def test_bridged_endpoint_poll (dbus , sysnet , nursery ):
1259+ poll_interval = 2500
1260+ config = f"""
1261+ [bus-owner]
1262+ endpoint_poll_ms = { poll_interval }
1263+ """
1264+
1265+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1266+ await mctpd .start_mctpd (nursery )
1267+
1268+ iface = mctpd .system .interfaces [0 ]
1269+ ep = mctpd .network .endpoints [0 ]
1270+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1271+
1272+ bridged_ep = [
1273+ Endpoint (iface , bytes (), types = [0 , 1 ]),
1274+ Endpoint (iface , bytes (), types = [0 , 1 ])
1275+ ]
1276+ for bep in bridged_ep :
1277+ mctpd .network .add_endpoint (bep )
1278+ ep .add_bridged_ep (bep )
1279+
1280+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1281+ assert new
1282+
1283+ mctp_obj = await dbus .get_proxy_object (MCTPD_C , MCTPD_MCTP_P )
1284+ mctp_objmgr = await mctp_obj .get_interface (DBUS_OBJECT_MANAGER_I )
1285+ endpoint_added = trio .Semaphore (initial_value = 0 )
1286+
1287+ # We expect two bridged endpoints to be discovered
1288+ expected_bridged_eps = len (bridged_ep )
1289+ bridged_endpoints_found = []
1290+
1291+ def ep_added (ep_path , content ):
1292+ if MCTPD_ENDPOINT_I in content :
1293+ bridged_endpoints_found .append (ep_path )
1294+ endpoint_added .release ()
1295+
1296+ await mctp_objmgr .on_interfaces_added (ep_added )
1297+
1298+ # Wait for all expected bridged endpoints to be discovered
1299+ with trio .move_on_after (poll_interval / 1000 * 2 ) as expected :
1300+ for i in range (expected_bridged_eps ):
1301+ await endpoint_added .acquire ()
1302+
1303+ # Verify we found all expected bridged endpoints
1304+ assert not expected .cancelled_caught , "Timeout waiting for bridged endpoints"
1305+ assert len (bridged_endpoints_found ) == expected_bridged_eps
1306+
1307+ res = await mctpd .stop_mctpd ()
1308+ assert res == 0
1309+
1310+ """ Test that all downstream endpoints are removed when the bridge
1311+ endpoint is removed"""
1312+ async def test_bridged_endpoint_remove (dbus , sysnet , nursery ):
1313+ poll_interval = 2500
1314+ config = f"""
1315+ [bus-owner]
1316+ endpoint_poll_ms = { poll_interval }
1317+ """
1318+
1319+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1320+ await mctpd .start_mctpd (nursery )
1321+
1322+ iface = mctpd .system .interfaces [0 ]
1323+ ep = mctpd .network .endpoints [0 ]
1324+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1325+
1326+ bridged_ep = [
1327+ Endpoint (iface , bytes (), types = [0 , 1 ]),
1328+ Endpoint (iface , bytes (), types = [0 , 1 ])
1329+ ]
1330+ for bep in bridged_ep :
1331+ mctpd .network .add_endpoint (bep )
1332+ ep .add_bridged_ep (bep )
1333+
1334+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1335+ assert new
1336+
1337+ # Wait for the bridged endpoints to be discovered
1338+ await trio .sleep (poll_interval / 1000 )
1339+ removed = trio .Semaphore (initial_value = 0 )
1340+ removed_eps = []
1341+
1342+ # Capture the removed endpoints
1343+ def ep_removed (ep_path , interfaces ):
1344+ if MCTPD_ENDPOINT_I in interfaces :
1345+ removed .release ()
1346+ removed_eps .append (ep_path )
1347+
1348+ mctp_obj = await dbus .get_proxy_object (MCTPD_C , MCTPD_MCTP_P )
1349+ mctp_objmgr = await mctp_obj .get_interface (DBUS_OBJECT_MANAGER_I )
1350+ await mctp_objmgr .on_interfaces_removed (ep_removed )
1351+
1352+ # Remove the bridge endpoint
1353+ bridge_obj = await mctpd_mctp_endpoint_control_obj (dbus , path )
1354+ await bridge_obj .call_remove ()
1355+
1356+ # Assert that all downstream endpoints were removed
1357+ assert len (removed_eps ) == (len (bridged_ep ) + 1 )
1358+ res = await mctpd .stop_mctpd ()
1359+ assert res == 0
1360+
1361+ """ Test that polling stops once endponit has been discovered """
1362+ async def test_bridged_endpoint_poll_stop (dbus , sysnet , nursery ):
1363+ poll_interval = 2500
1364+ config = f"""
1365+ [bus-owner]
1366+ endpoint_poll_ms = { poll_interval }
1367+ """
1368+
1369+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1370+ await mctpd .start_mctpd (nursery )
1371+
1372+ iface = mctpd .system .interfaces [0 ]
1373+ ep = mctpd .network .endpoints [0 ]
1374+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1375+ poll_count = 0
1376+
1377+ class BridgedEndpoint (Endpoint ):
1378+ async def handle_mctp_control (self , sock , src_addr , msg ):
1379+ flags , opcode = msg [0 :2 ]
1380+ if opcode == 0x2 : # Get Endpoint ID
1381+ nonlocal poll_count
1382+ poll_count += 1
1383+ return await super ().handle_mctp_control (sock , src_addr , msg )
1384+
1385+ bridged_ep = BridgedEndpoint (iface , bytes (), types = [0 , 1 ])
1386+ mctpd .network .add_endpoint (bridged_ep )
1387+ ep .add_bridged_ep (bridged_ep )
1388+
1389+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1390+ assert new
1391+
1392+ mctp_obj = await dbus .get_proxy_object (MCTPD_C , MCTPD_MCTP_P )
1393+ mctp_objmgr = await mctp_obj .get_interface (DBUS_OBJECT_MANAGER_I )
1394+ endpoint_added = trio .Semaphore (initial_value = 0 )
1395+ poll_count_by_discovery = 0
1396+
1397+ def ep_added (ep_path , content ):
1398+ if MCTPD_ENDPOINT_I in content :
1399+ nonlocal poll_count_by_discovery
1400+ poll_count_by_discovery = poll_count
1401+ endpoint_added .release ()
1402+
1403+ await mctp_objmgr .on_interfaces_added (ep_added )
1404+
1405+ # Wait longer than the poll interval for the bridged endpoint
1406+ # to be discovered
1407+ await trio .sleep (poll_interval / 1000 )
1408+
1409+ # We should have only poll until the discovery thus count should
1410+ # be the same even after longer wait.
1411+ assert poll_count == poll_count_by_discovery
1412+
1413+ res = await mctpd .stop_mctpd ()
1414+ assert res == 0
1415+
1416+ """ Test that polling continues until the endpoint is discovered """
1417+ async def test_bridged_endpoint_poll_continue (dbus , sysnet , nursery ):
1418+ poll_interval = 2500
1419+ config = f"""
1420+ [bus-owner]
1421+ endpoint_poll_ms = { poll_interval }
1422+ """
1423+
1424+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1425+ await mctpd .start_mctpd (nursery )
1426+
1427+ iface = mctpd .system .interfaces [0 ]
1428+ ep = mctpd .network .endpoints [0 ]
1429+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1430+ poll_count = 0
1431+
1432+ class BridgedEndpoint (Endpoint ):
1433+ async def handle_mctp_control (self , sock , src_addr , msg ):
1434+ flags , opcode = msg [0 :2 ]
1435+ # dont respond to simiulate device not accessible
1436+ # but increment poll count for the Get Endpoint ID
1437+ if opcode == 0x2 : # Get Endpoint ID
1438+ nonlocal poll_count
1439+ poll_count += 1
1440+ return None
1441+
1442+ bridged_ep = BridgedEndpoint (iface , bytes (), types = [0 , 1 ])
1443+ mctpd .network .add_endpoint (bridged_ep )
1444+ ep .add_bridged_ep (bridged_ep )
1445+
1446+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1447+ assert new
1448+
1449+ # Wait for sometime to continue polling
1450+ await trio .sleep (poll_interval / 1000 )
1451+
1452+ poll_count_before = poll_count
1453+ # Wait more to see if poll count increments
1454+ await trio .sleep (1 )
1455+ assert poll_count > poll_count_before
1456+
1457+ res = await mctpd .stop_mctpd ()
1458+ assert res == 0
0 commit comments