@@ -1506,3 +1506,205 @@ async def handle_mctp_control(self, sock, addr, data):
15061506 # exit mctpd
15071507 res = await mctpd .stop_mctpd ()
15081508 assert res == 0
1509+ """ Test that we use endpoint poll interval from the config and
1510+ that we discover bridged endpoints via polling"""
1511+ async def test_bridged_endpoint_poll (dbus , sysnet , nursery , autojump_clock ):
1512+ poll_interval = 2500
1513+ config = f"""
1514+ [bus-owner]
1515+ endpoint_poll_ms = { poll_interval }
1516+ """
1517+
1518+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1519+ await mctpd .start_mctpd (nursery )
1520+
1521+ iface = mctpd .system .interfaces [0 ]
1522+ ep = mctpd .network .endpoints [0 ]
1523+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1524+
1525+ bridged_ep = [
1526+ Endpoint (iface , bytes (), types = [0 , 1 ]),
1527+ Endpoint (iface , bytes (), types = [0 , 1 ])
1528+ ]
1529+ for bep in bridged_ep :
1530+ mctpd .network .add_endpoint (bep )
1531+ ep .add_bridged_ep (bep )
1532+
1533+ mctp_obj = await dbus .get_proxy_object (MCTPD_C , MCTPD_MCTP_P )
1534+ mctp_objmgr = await mctp_obj .get_interface (DBUS_OBJECT_MANAGER_I )
1535+ endpoint_added = trio .Semaphore (initial_value = 0 )
1536+
1537+ # We expect two bridged endpoints to be discovered
1538+ expected_bridged_eps = len (bridged_ep )
1539+ bridged_endpoints_found = []
1540+
1541+ def ep_added (ep_path , content ):
1542+ if MCTPD_ENDPOINT_I in content :
1543+ bridged_endpoints_found .append (ep_path )
1544+ endpoint_added .release ()
1545+
1546+ await mctp_objmgr .on_interfaces_added (ep_added )
1547+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1548+ assert new
1549+
1550+ # Wait for all expected bridged endpoints to be discovered
1551+ with trio .move_on_after (poll_interval / 1000 * 2 ) as expected :
1552+ for i in range (expected_bridged_eps ):
1553+ await endpoint_added .acquire ()
1554+
1555+ # Verify we found all expected bridged endpoints
1556+ assert not expected .cancelled_caught , "Timeout waiting for bridged endpoints"
1557+ assert len (bridged_endpoints_found ) == expected_bridged_eps
1558+
1559+ res = await mctpd .stop_mctpd ()
1560+ assert res == 0
1561+
1562+ """ Test that all downstream endpoints are removed when the bridge
1563+ endpoint is removed"""
1564+ async def test_bridged_endpoint_remove (dbus , sysnet , nursery , autojump_clock ):
1565+ poll_interval = 2500
1566+ config = f"""
1567+ [bus-owner]
1568+ endpoint_poll_ms = { poll_interval }
1569+ """
1570+
1571+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1572+ await mctpd .start_mctpd (nursery )
1573+
1574+ iface = mctpd .system .interfaces [0 ]
1575+ ep = mctpd .network .endpoints [0 ]
1576+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1577+
1578+ bridged_ep = [
1579+ Endpoint (iface , bytes (), types = [0 , 1 ]),
1580+ Endpoint (iface , bytes (), types = [0 , 1 ])
1581+ ]
1582+ for bep in bridged_ep :
1583+ mctpd .network .add_endpoint (bep )
1584+ ep .add_bridged_ep (bep )
1585+
1586+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1587+ assert new
1588+
1589+ # Wait for the bridged endpoints to be discovered
1590+ await trio .sleep ((poll_interval * 2 ) / 1000 )
1591+ removed = trio .Semaphore (initial_value = 0 )
1592+ removed_eps = []
1593+
1594+ # Capture the removed endpoints
1595+ def ep_removed (ep_path , interfaces ):
1596+ if MCTPD_ENDPOINT_I in interfaces :
1597+ removed .release ()
1598+ removed_eps .append (ep_path )
1599+
1600+ mctp_obj = await dbus .get_proxy_object (MCTPD_C , MCTPD_MCTP_P )
1601+ mctp_objmgr = await mctp_obj .get_interface (DBUS_OBJECT_MANAGER_I )
1602+ await mctp_objmgr .on_interfaces_removed (ep_removed )
1603+
1604+ # Remove the bridge endpoint
1605+ bridge_obj = await mctpd_mctp_endpoint_control_obj (dbus , path )
1606+ await bridge_obj .call_remove ()
1607+
1608+ # Assert that all downstream endpoints were removed
1609+ assert len (removed_eps ) == (len (bridged_ep ) + 1 )
1610+ res = await mctpd .stop_mctpd ()
1611+ assert res == 0
1612+
1613+ """ Test that polling stops once endponit has been discovered """
1614+ async def test_bridged_endpoint_poll_stop (dbus , sysnet , nursery , autojump_clock ):
1615+ poll_interval = 2500
1616+ config = f"""
1617+ [bus-owner]
1618+ endpoint_poll_ms = { poll_interval }
1619+ """
1620+
1621+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1622+ await mctpd .start_mctpd (nursery )
1623+
1624+ iface = mctpd .system .interfaces [0 ]
1625+ ep = mctpd .network .endpoints [0 ]
1626+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1627+ poll_count = 0
1628+
1629+ class BridgedEndpoint (Endpoint ):
1630+ async def handle_mctp_control (self , sock , src_addr , msg ):
1631+ flags , opcode = msg [0 :2 ]
1632+ if opcode == 0x2 : # Get Endpoint ID
1633+ nonlocal poll_count
1634+ poll_count += 1
1635+ return await super ().handle_mctp_control (sock , src_addr , msg )
1636+
1637+ bridged_ep = BridgedEndpoint (iface , bytes (), types = [0 , 1 ])
1638+ mctpd .network .add_endpoint (bridged_ep )
1639+ ep .add_bridged_ep (bridged_ep )
1640+
1641+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1642+ assert new
1643+
1644+ mctp_obj = await dbus .get_proxy_object (MCTPD_C , MCTPD_MCTP_P )
1645+ mctp_objmgr = await mctp_obj .get_interface (DBUS_OBJECT_MANAGER_I )
1646+ endpoint_added = trio .Semaphore (initial_value = 0 )
1647+ poll_count_by_discovery = 0
1648+
1649+ def ep_added (ep_path , content ):
1650+ if MCTPD_ENDPOINT_I in content :
1651+ nonlocal poll_count_by_discovery
1652+ poll_count_by_discovery = poll_count
1653+ endpoint_added .release ()
1654+
1655+ await mctp_objmgr .on_interfaces_added (ep_added )
1656+
1657+ # Wait longer than the poll interval for the bridged endpoint
1658+ # to be discovered
1659+ await trio .sleep (poll_interval / 1000 )
1660+
1661+ # We should have only poll until the discovery thus count should
1662+ # be the same even after longer wait.
1663+ assert poll_count == poll_count_by_discovery
1664+
1665+ res = await mctpd .stop_mctpd ()
1666+ assert res == 0
1667+
1668+ """ Test that polling continues until the endpoint is discovered """
1669+ async def test_bridged_endpoint_poll_continue (dbus , sysnet , nursery , autojump_clock ):
1670+ poll_interval = 2500
1671+ config = f"""
1672+ [bus-owner]
1673+ endpoint_poll_ms = { poll_interval }
1674+ """
1675+
1676+ mctpd = MctpdWrapper (dbus , sysnet , config = config )
1677+ await mctpd .start_mctpd (nursery )
1678+
1679+ iface = mctpd .system .interfaces [0 ]
1680+ ep = mctpd .network .endpoints [0 ]
1681+ mctp = await mctpd_mctp_iface_obj (dbus , iface )
1682+ poll_count = 0
1683+
1684+ class BridgedEndpoint (Endpoint ):
1685+ async def handle_mctp_control (self , sock , src_addr , msg ):
1686+ flags , opcode = msg [0 :2 ]
1687+ # dont respond to simiulate device not accessible
1688+ # but increment poll count for the Get Endpoint ID
1689+ if opcode == 0x2 : # Get Endpoint ID
1690+ nonlocal poll_count
1691+ poll_count += 1
1692+ return None
1693+
1694+ bridged_ep = BridgedEndpoint (iface , bytes (), types = [0 , 1 ])
1695+ mctpd .network .add_endpoint (bridged_ep )
1696+ ep .add_bridged_ep (bridged_ep )
1697+
1698+ (eid , _ , path , new ) = await mctp .call_assign_endpoint (ep .lladdr )
1699+ assert new
1700+
1701+ # Wait for sometime to continue polling
1702+ await trio .sleep (poll_interval / 1000 )
1703+
1704+ poll_count_before = poll_count
1705+ # Wait more to see if poll count increments
1706+ await trio .sleep (1 )
1707+ assert poll_count > poll_count_before
1708+
1709+ res = await mctpd .stop_mctpd ()
1710+ assert res == 0
0 commit comments