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