@@ -1376,3 +1376,207 @@ async def test_register_vdm_type_support_errors(dbus, mctpd):
13761376 with pytest .raises (asyncdbus .errors .DBusError ) as ex :
13771377 await mctp .call_register_vdm_type_support (0x00 , v_type , 0x0001 )
13781378 assert str (ex .value ) == "VDM type already registered"
1379+
1380+ """ Test that we use endpoint poll interval from the config and
1381+ that we discover bridged endpoints via polling"""
1382+ async def test_bridged_endpoint_poll (dbus , sysnet , nursery , autojump_clock ):
1383+ poll_interval = 2500
1384+ config = f"""
1385+ [bus-owner]
1386+ endpoint_poll_ms = { poll_interval }
1387+ """
1388+
1389+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1390+ await mctpd .start_mctpd (nursery )
1391+
1392+ iface = mctpd .system .interfaces [0 ]
1393+ ep = mctpd .network .endpoints [0 ]
1394+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1395+
1396+ bridged_ep = [
1397+ Endpoint (iface , bytes (), types = [0 , 1 ]),
1398+ Endpoint (iface , bytes (), types = [0 , 1 ])
1399+ ]
1400+ for bep in bridged_ep :
1401+ mctpd .network .add_endpoint (bep )
1402+ ep .add_bridged_ep (bep )
1403+
1404+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1405+ assert new
1406+
1407+ mctp_obj = await dbus .get_proxy_object (MCTPD_C , MCTPD_MCTP_P )
1408+ mctp_objmgr = await mctp_obj .get_interface (DBUS_OBJECT_MANAGER_I )
1409+ endpoint_added = trio .Semaphore (initial_value = 0 )
1410+
1411+ # We expect two bridged endpoints to be discovered
1412+ expected_bridged_eps = len (bridged_ep )
1413+ bridged_endpoints_found = []
1414+
1415+ def ep_added (ep_path , content ):
1416+ if MCTPD_ENDPOINT_I in content :
1417+ bridged_endpoints_found .append (ep_path )
1418+ endpoint_added .release ()
1419+
1420+ await mctp_objmgr .on_interfaces_added (ep_added )
1421+
1422+ # Wait for all expected bridged endpoints to be discovered
1423+ with trio .move_on_after (poll_interval / 1000 * 2 ) as expected :
1424+ for i in range (expected_bridged_eps ):
1425+ await endpoint_added .acquire ()
1426+
1427+ # Verify we found all expected bridged endpoints
1428+ assert not expected .cancelled_caught , "Timeout waiting for bridged endpoints"
1429+ assert len (bridged_endpoints_found ) == expected_bridged_eps
1430+
1431+ res = await mctpd .stop_mctpd ()
1432+ assert res == 0
1433+
1434+ """ Test that all downstream endpoints are removed when the bridge
1435+ endpoint is removed"""
1436+ async def test_bridged_endpoint_remove (dbus , sysnet , nursery , autojump_clock ):
1437+ poll_interval = 2500
1438+ config = f"""
1439+ [bus-owner]
1440+ endpoint_poll_ms = { poll_interval }
1441+ """
1442+
1443+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1444+ await mctpd .start_mctpd (nursery )
1445+
1446+ iface = mctpd .system .interfaces [0 ]
1447+ ep = mctpd .network .endpoints [0 ]
1448+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1449+
1450+ bridged_ep = [
1451+ Endpoint (iface , bytes (), types = [0 , 1 ]),
1452+ Endpoint (iface , bytes (), types = [0 , 1 ])
1453+ ]
1454+ for bep in bridged_ep :
1455+ mctpd .network .add_endpoint (bep )
1456+ ep .add_bridged_ep (bep )
1457+
1458+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1459+ assert new
1460+
1461+ # Wait for the bridged endpoints to be discovered
1462+ await trio .sleep (poll_interval / 1000 )
1463+ removed = trio .Semaphore (initial_value = 0 )
1464+ removed_eps = []
1465+
1466+ # Capture the removed endpoints
1467+ def ep_removed (ep_path , interfaces ):
1468+ if MCTPD_ENDPOINT_I in interfaces :
1469+ removed .release ()
1470+ removed_eps .append (ep_path )
1471+
1472+ mctp_obj = await dbus .get_proxy_object (MCTPD_C , MCTPD_MCTP_P )
1473+ mctp_objmgr = await mctp_obj .get_interface (DBUS_OBJECT_MANAGER_I )
1474+ await mctp_objmgr .on_interfaces_removed (ep_removed )
1475+
1476+ # Remove the bridge endpoint
1477+ bridge_obj = await mctpd_mctp_endpoint_control_obj (dbus , path )
1478+ await bridge_obj .call_remove ()
1479+
1480+ # Assert that all downstream endpoints were removed
1481+ assert len (removed_eps ) == (len (bridged_ep ) + 1 )
1482+ res = await mctpd .stop_mctpd ()
1483+ assert res == 0
1484+
1485+ """ Test that polling stops once endponit has been discovered """
1486+ async def test_bridged_endpoint_poll_stop (dbus , sysnet , nursery , autojump_clock ):
1487+ poll_interval = 2500
1488+ config = f"""
1489+ [bus-owner]
1490+ endpoint_poll_ms = { poll_interval }
1491+ """
1492+
1493+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1494+ await mctpd .start_mctpd (nursery )
1495+
1496+ iface = mctpd .system .interfaces [0 ]
1497+ ep = mctpd .network .endpoints [0 ]
1498+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1499+ poll_count = 0
1500+
1501+ class BridgedEndpoint (Endpoint ):
1502+ async def handle_mctp_control (self , sock , src_addr , msg ):
1503+ flags , opcode = msg [0 :2 ]
1504+ if opcode == 0x2 : # Get Endpoint ID
1505+ nonlocal poll_count
1506+ poll_count += 1
1507+ return await super ().handle_mctp_control (sock , src_addr , msg )
1508+
1509+ bridged_ep = BridgedEndpoint (iface , bytes (), types = [0 , 1 ])
1510+ mctpd .network .add_endpoint (bridged_ep )
1511+ ep .add_bridged_ep (bridged_ep )
1512+
1513+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1514+ assert new
1515+
1516+ mctp_obj = await dbus .get_proxy_object (MCTPD_C , MCTPD_MCTP_P )
1517+ mctp_objmgr = await mctp_obj .get_interface (DBUS_OBJECT_MANAGER_I )
1518+ endpoint_added = trio .Semaphore (initial_value = 0 )
1519+ poll_count_by_discovery = 0
1520+
1521+ def ep_added (ep_path , content ):
1522+ if MCTPD_ENDPOINT_I in content :
1523+ nonlocal poll_count_by_discovery
1524+ poll_count_by_discovery = poll_count
1525+ endpoint_added .release ()
1526+
1527+ await mctp_objmgr .on_interfaces_added (ep_added )
1528+
1529+ # Wait longer than the poll interval for the bridged endpoint
1530+ # to be discovered
1531+ await trio .sleep (poll_interval / 1000 )
1532+
1533+ # We should have only poll until the discovery thus count should
1534+ # be the same even after longer wait.
1535+ assert poll_count == poll_count_by_discovery
1536+
1537+ res = await mctpd .stop_mctpd ()
1538+ assert res == 0
1539+
1540+ """ Test that polling continues until the endpoint is discovered """
1541+ async def test_bridged_endpoint_poll_continue (dbus , sysnet , nursery , autojump_clock ):
1542+ poll_interval = 2500
1543+ config = f"""
1544+ [bus-owner]
1545+ endpoint_poll_ms = { poll_interval }
1546+ """
1547+
1548+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1549+ await mctpd .start_mctpd (nursery )
1550+
1551+ iface = mctpd .system .interfaces [0 ]
1552+ ep = mctpd .network .endpoints [0 ]
1553+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1554+ poll_count = 0
1555+
1556+ class BridgedEndpoint (Endpoint ):
1557+ async def handle_mctp_control (self , sock , src_addr , msg ):
1558+ flags , opcode = msg [0 :2 ]
1559+ # dont respond to simiulate device not accessible
1560+ # but increment poll count for the Get Endpoint ID
1561+ if opcode == 0x2 : # Get Endpoint ID
1562+ nonlocal poll_count
1563+ poll_count += 1
1564+ return None
1565+
1566+ bridged_ep = BridgedEndpoint (iface , bytes (), types = [0 , 1 ])
1567+ mctpd .network .add_endpoint (bridged_ep )
1568+ ep .add_bridged_ep (bridged_ep )
1569+
1570+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1571+ assert new
1572+
1573+ # Wait for sometime to continue polling
1574+ await trio .sleep (poll_interval / 1000 )
1575+
1576+ poll_count_before = poll_count
1577+ # Wait more to see if poll count increments
1578+ await trio .sleep (1 )
1579+ assert poll_count > poll_count_before
1580+
1581+ res = await mctpd .stop_mctpd ()
1582+ assert res == 0
0 commit comments