@@ -1289,3 +1289,207 @@ async def test_get_message_types(dbus, mctpd):
12891289 cmd = MCTPControlCommand (True , 0 , 0x04 , bytes ([0x05 ]))
12901290 rsp = await ep .send_control (mctpd .network .mctp_socket , cmd )
12911291 assert rsp .hex (' ' ) == '00 04 00 01 f4 f3 f2 f1'
1292+
1293+ """ Test that we use endpoint poll interval from the config and
1294+ that we discover bridged endpoints via polling"""
1295+ async def test_bridged_endpoint_poll (dbus , sysnet , nursery ):
1296+ poll_interval = 2500
1297+ config = f"""
1298+ [bus-owner]
1299+ endpoint_poll_ms = { poll_interval }
1300+ """
1301+
1302+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1303+ await mctpd .start_mctpd (nursery )
1304+
1305+ iface = mctpd .system .interfaces [0 ]
1306+ ep = mctpd .network .endpoints [0 ]
1307+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1308+
1309+ bridged_ep = [
1310+ Endpoint (iface , bytes (), types = [0 , 1 ]),
1311+ Endpoint (iface , bytes (), types = [0 , 1 ])
1312+ ]
1313+ for bep in bridged_ep :
1314+ mctpd .network .add_endpoint (bep )
1315+ ep .add_bridged_ep (bep )
1316+
1317+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1318+ assert new
1319+
1320+ mctp_obj = await dbus .get_proxy_object (MCTPD_C , MCTPD_MCTP_P )
1321+ mctp_objmgr = await mctp_obj .get_interface (DBUS_OBJECT_MANAGER_I )
1322+ endpoint_added = trio .Semaphore (initial_value = 0 )
1323+
1324+ # We expect two bridged endpoints to be discovered
1325+ expected_bridged_eps = len (bridged_ep )
1326+ bridged_endpoints_found = []
1327+
1328+ def ep_added (ep_path , content ):
1329+ if MCTPD_ENDPOINT_I in content :
1330+ bridged_endpoints_found .append (ep_path )
1331+ endpoint_added .release ()
1332+
1333+ await mctp_objmgr .on_interfaces_added (ep_added )
1334+
1335+ # Wait for all expected bridged endpoints to be discovered
1336+ with trio .move_on_after (poll_interval / 1000 * 2 ) as expected :
1337+ for i in range (expected_bridged_eps ):
1338+ await endpoint_added .acquire ()
1339+
1340+ # Verify we found all expected bridged endpoints
1341+ assert not expected .cancelled_caught , "Timeout waiting for bridged endpoints"
1342+ assert len (bridged_endpoints_found ) == expected_bridged_eps
1343+
1344+ res = await mctpd .stop_mctpd ()
1345+ assert res == 0
1346+
1347+ """ Test that all downstream endpoints are removed when the bridge
1348+ endpoint is removed"""
1349+ async def test_bridged_endpoint_remove (dbus , sysnet , nursery ):
1350+ poll_interval = 2500
1351+ config = f"""
1352+ [bus-owner]
1353+ endpoint_poll_ms = { poll_interval }
1354+ """
1355+
1356+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1357+ await mctpd .start_mctpd (nursery )
1358+
1359+ iface = mctpd .system .interfaces [0 ]
1360+ ep = mctpd .network .endpoints [0 ]
1361+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1362+
1363+ bridged_ep = [
1364+ Endpoint (iface , bytes (), types = [0 , 1 ]),
1365+ Endpoint (iface , bytes (), types = [0 , 1 ])
1366+ ]
1367+ for bep in bridged_ep :
1368+ mctpd .network .add_endpoint (bep )
1369+ ep .add_bridged_ep (bep )
1370+
1371+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1372+ assert new
1373+
1374+ # Wait for the bridged endpoints to be discovered
1375+ await trio .sleep (poll_interval / 1000 )
1376+ removed = trio .Semaphore (initial_value = 0 )
1377+ removed_eps = []
1378+
1379+ # Capture the removed endpoints
1380+ def ep_removed (ep_path , interfaces ):
1381+ if MCTPD_ENDPOINT_I in interfaces :
1382+ removed .release ()
1383+ removed_eps .append (ep_path )
1384+
1385+ mctp_obj = await dbus .get_proxy_object (MCTPD_C , MCTPD_MCTP_P )
1386+ mctp_objmgr = await mctp_obj .get_interface (DBUS_OBJECT_MANAGER_I )
1387+ await mctp_objmgr .on_interfaces_removed (ep_removed )
1388+
1389+ # Remove the bridge endpoint
1390+ bridge_obj = await mctpd_mctp_endpoint_control_obj (dbus , path )
1391+ await bridge_obj .call_remove ()
1392+
1393+ # Assert that all downstream endpoints were removed
1394+ assert len (removed_eps ) == (len (bridged_ep ) + 1 )
1395+ res = await mctpd .stop_mctpd ()
1396+ assert res == 0
1397+
1398+ """ Test that polling stops once endponit has been discovered """
1399+ async def test_bridged_endpoint_poll_stop (dbus , sysnet , nursery ):
1400+ poll_interval = 2500
1401+ config = f"""
1402+ [bus-owner]
1403+ endpoint_poll_ms = { poll_interval }
1404+ """
1405+
1406+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1407+ await mctpd .start_mctpd (nursery )
1408+
1409+ iface = mctpd .system .interfaces [0 ]
1410+ ep = mctpd .network .endpoints [0 ]
1411+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1412+ poll_count = 0
1413+
1414+ class BridgedEndpoint (Endpoint ):
1415+ async def handle_mctp_control (self , sock , src_addr , msg ):
1416+ flags , opcode = msg [0 :2 ]
1417+ if opcode == 0x2 : # Get Endpoint ID
1418+ nonlocal poll_count
1419+ poll_count += 1
1420+ return await super ().handle_mctp_control (sock , src_addr , msg )
1421+
1422+ bridged_ep = BridgedEndpoint (iface , bytes (), types = [0 , 1 ])
1423+ mctpd .network .add_endpoint (bridged_ep )
1424+ ep .add_bridged_ep (bridged_ep )
1425+
1426+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1427+ assert new
1428+
1429+ mctp_obj = await dbus .get_proxy_object (MCTPD_C , MCTPD_MCTP_P )
1430+ mctp_objmgr = await mctp_obj .get_interface (DBUS_OBJECT_MANAGER_I )
1431+ endpoint_added = trio .Semaphore (initial_value = 0 )
1432+ poll_count_by_discovery = 0
1433+
1434+ def ep_added (ep_path , content ):
1435+ if MCTPD_ENDPOINT_I in content :
1436+ nonlocal poll_count_by_discovery
1437+ poll_count_by_discovery = poll_count
1438+ endpoint_added .release ()
1439+
1440+ await mctp_objmgr .on_interfaces_added (ep_added )
1441+
1442+ # Wait longer than the poll interval for the bridged endpoint
1443+ # to be discovered
1444+ await trio .sleep (poll_interval / 1000 )
1445+
1446+ # We should have only poll until the discovery thus count should
1447+ # be the same even after longer wait.
1448+ assert poll_count == poll_count_by_discovery
1449+
1450+ res = await mctpd .stop_mctpd ()
1451+ assert res == 0
1452+
1453+ """ Test that polling continues until the endpoint is discovered """
1454+ async def test_bridged_endpoint_poll_continue (dbus , sysnet , nursery ):
1455+ poll_interval = 2500
1456+ config = f"""
1457+ [bus-owner]
1458+ endpoint_poll_ms = { poll_interval }
1459+ """
1460+
1461+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1462+ await mctpd .start_mctpd (nursery )
1463+
1464+ iface = mctpd .system .interfaces [0 ]
1465+ ep = mctpd .network .endpoints [0 ]
1466+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1467+ poll_count = 0
1468+
1469+ class BridgedEndpoint (Endpoint ):
1470+ async def handle_mctp_control (self , sock , src_addr , msg ):
1471+ flags , opcode = msg [0 :2 ]
1472+ # dont respond to simiulate device not accessible
1473+ # but increment poll count for the Get Endpoint ID
1474+ if opcode == 0x2 : # Get Endpoint ID
1475+ nonlocal poll_count
1476+ poll_count += 1
1477+ return None
1478+
1479+ bridged_ep = BridgedEndpoint (iface , bytes (), types = [0 , 1 ])
1480+ mctpd .network .add_endpoint (bridged_ep )
1481+ ep .add_bridged_ep (bridged_ep )
1482+
1483+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1484+ assert new
1485+
1486+ # Wait for sometime to continue polling
1487+ await trio .sleep (poll_interval / 1000 )
1488+
1489+ poll_count_before = poll_count
1490+ # Wait more to see if poll count increments
1491+ await trio .sleep (1 )
1492+ assert poll_count > poll_count_before
1493+
1494+ res = await mctpd .stop_mctpd ()
1495+ assert res == 0
0 commit comments