@@ -651,5 +651,112 @@ def test_06_dhcp_default_route_for_vrf(self):
651651 while process_named_running ('dhclient' , cmdline = interface , timeout = 10 ):
652652 sleep (0.250 )
653653
654+ def test_07_dhcp_interface_static_routes (self ):
655+ # Test static routes using dhcp-interface option
656+ # When running via vyos-build under the QEMU environment a local DHCP
657+ # server is available. This test verifies that static routes with
658+ # dhcp-interface are configured correctly.
659+ if not os .path .exists ('/tmp/vyos.smoketests.hint' ):
660+ self .skipTest ('Not running under VyOS CI/CD QEMU environment!' )
661+
662+ dhcp_interface = 'eth0'
663+ interface_path = ['interfaces' , 'ethernet' , dhcp_interface ]
664+
665+ # Configure DHCP on the interface
666+ self .cli_set (interface_path + ['address' , 'dhcp' ])
667+
668+ # Commit configuration
669+ self .cli_commit ()
670+
671+ # Wait for dhclient to receive IP address
672+ sleep (5 )
673+
674+ # Configure static routes with dhcp-interface
675+ dhcp_routes = {
676+ '10.10.0.0/16' : {
677+ 'dhcp_interface' : [dhcp_interface ],
678+ },
679+ '192.168.100.0/24' : {
680+ 'dhcp_interface' : [dhcp_interface ],
681+ },
682+ }
683+
684+ # Configure the static routes
685+ for route , route_config in dhcp_routes .items ():
686+ base = base_path + ['route' , route ]
687+ if 'dhcp_interface' in route_config :
688+ for dhcp_if in route_config ['dhcp_interface' ]:
689+ self .cli_set (base + ['dhcp-interface' , dhcp_if ])
690+
691+ # Commit configuration
692+ self .cli_commit ()
693+
694+ # Verify that the DHCP hook interface list file is created
695+ dhcp_hook_iflist = '/tmp/static_dhcp_interfaces'
696+ self .assertTrue (
697+ os .path .exists (dhcp_hook_iflist ),
698+ 'DHCP hook interface list file should be created' ,
699+ )
700+
701+ # Read the interface list file and verify it contains our interface
702+ with open (dhcp_hook_iflist , 'r' ) as f :
703+ interface_list = f .read ().strip ()
704+ self .assertIn (
705+ dhcp_interface ,
706+ interface_list ,
707+ f'Interface { dhcp_interface } should be in hook interface list' ,
708+ )
709+
710+ # Get the DHCP router for verification
711+ router = get_dhcp_router (dhcp_interface )
712+ self .assertIsNotNone (router , 'DHCP router should be available' )
713+
714+ # Verify FRR configuration contains the static routes with DHCP router
715+ frrconfig = self .getFRRconfig ('ip route' )
716+
717+ for route in dhcp_routes .keys ():
718+ expected_route = f'ip route { route } { router } { dhcp_interface } '
719+ self .assertIn (
720+ expected_route ,
721+ frrconfig ,
722+ f'Static route { route } with dhcp-interface should be in FRR config' ,
723+ )
724+
725+ # Test table-based routes with dhcp-interface
726+ table_id = '100'
727+ table_route = '10.20.0.0/16'
728+ table_base = base_path + ['table' , table_id , 'route' , table_route ]
729+ self .cli_set (table_base + ['dhcp-interface' , dhcp_interface ])
730+ self .cli_commit ()
731+
732+ # Verify table route in FRR config
733+ frrconfig = self .getFRRconfig ('ip route' )
734+ expected_table_route = (
735+ f'ip route { table_route } { router } { dhcp_interface } table { table_id } '
736+ )
737+ self .assertIn (
738+ expected_table_route ,
739+ frrconfig ,
740+ f'Table static route { table_route } with dhcp-interface should be in FRR config' ,
741+ )
742+
743+ # Clean up - remove DHCP configuration
744+ self .cli_delete (interface_path + ['address' ])
745+ self .cli_commit ()
746+
747+ # Wait for dhclient to stop
748+ while process_named_running ('dhclient' , cmdline = dhcp_interface , timeout = 10 ):
749+ sleep (0.250 )
750+
751+ # Verify that the hook interface list file is cleaned up when no dhcp-interface routes exist
752+ self .cli_delete (base_path )
753+ self .cli_commit ()
754+
755+ # The interface list file should be removed when no dhcp-interface routes are configured
756+ self .assertFalse (
757+ os .path .exists (dhcp_hook_iflist ),
758+ 'DHCP hook interface list file should be removed when no dhcp-interface routes exist' ,
759+ )
760+
654761if __name__ == '__main__' :
655762 unittest .main (verbosity = 2 , failfast = VyOSUnitTestSHIM .TestCase .debug_on ())
0 commit comments