@ -1,12 +1,7 @@
 
			
		
	
		
		
			
				
					
					use   std ::collections ::HashMap ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					use   aya ::{ use   aya ::{  
			
		
	
		
		
			
				
					
					     programs ::{      programs ::{ tc ::TcAttachOptions ,   LinkOrder ,   ProgramId ,   SchedClassifier ,   TcAttachType } ,  
			
				
				
			
		
	
		
		
			
				
					
					         tc ::{ SchedClassifierLink ,   TcAttachOptions } ,  
			
		
	
		
		
			
				
					
					         LinkOrder ,   ProgramId ,   SchedClassifier ,   TcAttachType ,  
			
		
	
		
		
			
				
					
					     } ,  
			
		
	
		
		
	
		
		
			
				
					
					     util ::KernelVersion ,      util ::KernelVersion ,  
			
		
	
		
		
			
				
					
					     Ebpf ,   EbpfLoader ,      Ebpf ,  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					} ; } ;  
			
		
	
		
		
			
				
					
					use   test_log ::test ; use   test_log ::test ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -25,110 +20,97 @@ async fn tcx() {
 
			
		
	
		
		
			
				
					
					     // We need a dedicated `Ebpf` instance for each program that we load
      // We need a dedicated `Ebpf` instance for each program that we load
  
			
		
	
		
		
			
				
					
					     // since TCX does not allow the same program ID to be attached multiple
      // since TCX does not allow the same program ID to be attached multiple
  
			
		
	
		
		
			
				
					
					     // times to the same interface/direction.
      // times to the same interface/direction.
  
			
		
	
		
		
			
				
					
					     let   mut   attached_programs : HashMap < & str ,   ( Ebpf ,   SchedClassifierLink ) >   =   HashMap ::new ( ) ;      //
  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					     // Variables declared within this macro are within a closure scope to avoid
  
			
		
	
		
		
			
				
					
					     // variable name conflicts.
  
			
		
	
		
		
			
				
					
					     //
  
			
		
	
		
		
			
				
					
					     // Yields a tuple of the `Ebpf` which must remain in scope for the duration
  
			
		
	
		
		
			
				
					
					     // of the test, and the link ID of the attached program.
  
			
		
	
		
		
			
				
					
					     macro_rules!   attach_program_with_linkorder   {      macro_rules!   attach_program_with_linkorder   {  
			
		
	
		
		
			
				
					
					         ( $name :literal , $link_order :expr )   = >   { {          ( $ link_order:expr )   = >   { {  
			
				
				
			
		
	
		
		
			
				
					
					             let   mut   loader   =   EbpfLoader ::new ( ) . load ( crate ::TCX ) . unwrap ( ) ;              let   mut   ebpf  =   Ebpf :: load ( crate ::TCX ) . unwrap ( ) ;  
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					             let   program : & mut   SchedClassifier   =              let   program : & mut   SchedClassifier   =  
			
		
	
		
		
			
				
					
					                 loader . program_mut ( "tcx_next" ) . unwrap ( ) . try_into ( ) . unwrap ( ) ;                  ebpf . program_mut ( "tcx_next" ) . unwrap ( ) . try_into ( ) . unwrap ( ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             program . load ( ) . unwrap ( ) ;              program . load ( ) . unwrap ( ) ;  
			
		
	
		
		
			
				
					
					             let   options   =   TcAttachOptions ::TcxOrder ( $link_order ) ;  
			
		
	
		
		
			
				
					
					             let   link_id   =   program              let   link_id   =   program  
			
		
	
		
		
			
				
					
					                 . attach_with_options ( "lo" ,   TcAttachType ::Ingress ,   options )                  . attach_with_options (  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     "lo" ,  
			
		
	
		
		
			
				
					
					                     TcAttachType ::Ingress ,  
			
		
	
		
		
			
				
					
					                     TcAttachOptions ::TcxOrder ( $link_order ) ,  
			
		
	
		
		
			
				
					
					                 )  
			
		
	
		
		
			
				
					
					                 . unwrap ( ) ;                  . unwrap ( ) ;  
			
		
	
		
		
			
				
					
					             let   link   =   program . take_link ( link_id ) . unwrap ( ) ;              ( ebpf ,   link_id )  
			
				
				
			
		
	
		
		
			
				
					
					             attached_programs . insert ( $name ,   ( loader ,   link ) ) ;  
			
		
	
		
		
	
		
		
			
				
					
					         } } ;          } } ;  
			
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     // TODO: Assert in position 4 at the end of the test.
      let   ( default ,   _ )   =   attach_program_with_linkorder ! ( LinkOrder ::default ( ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					     attach_program_with_linkorder ! ( "default" ,   LinkOrder ::default ( ) ) ;      let   ( first ,   _ )   =   attach_program_with_linkorder ! ( LinkOrder ::first ( ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					     // TODO: Assert in position 1 at the end of the test.
      let   ( mut   last ,   last_link_id )   =   attach_program_with_linkorder ! ( LinkOrder ::last ( ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					     attach_program_with_linkorder ! ( "first" ,   LinkOrder ::first ( ) ) ; 
 
			
				
				
			
		
	
		
		
			
				
					
					     // TODO: Assert in position 7 at the end of the test.
      let   default_prog : & SchedClassifier   =   default . program ( "tcx_next" ) . unwrap ( ) . try_into ( ) . unwrap ( ) ;  
			
				
				
			
		
	
		
		
			
				
					
					     attach_program_with_linkorder ! ( "last" ,   LinkOrder ::last ( ) ) ;      let   first_prog : & SchedClassifier   =   first . program ( "tcx_next" ) . unwrap ( ) . try_into ( ) . unwrap ( ) ;  
			
				
				
			
		
	
		
		
			
				
					
					     // TODO: Assert in position 6 at the end of the test.
      let   last_prog : & mut   SchedClassifier   =   last . program_mut ( "tcx_next" ) . unwrap ( ) . try_into ( ) . unwrap ( ) ;  
			
				
				
			
		
	
		
		
			
				
					
					     attach_program_with_linkorder ! ( 
 
			
				
				
			
		
	
		
		
			
				
					
					         "before_last" ,      let   last_link   =   last_prog . take_link ( last_link_id ) . unwrap ( ) ;  
			
				
				
			
		
	
		
		
			
				
					
					         LinkOrder ::before_link ( & attached_programs . get ( "last" ) . unwrap ( ) . 1 ) . unwrap ( ) 
 
			
				
				
			
		
	
		
		
			
				
					
					     ) ;      let   ( before_last ,   _ )   =  
			
				
				
			
		
	
		
		
			
				
					
					     // TODO: Assert in position 8 at the end of the test.
          attach_program_with_linkorder ! ( LinkOrder ::before_link ( & last_link ) . unwrap ( ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					     attach_program_with_linkorder ! (      let   ( after_last ,   _ )   =  
			
				
				
			
		
	
		
		
			
				
					
					         "after_last" ,          attach_program_with_linkorder ! ( LinkOrder ::after_link ( & last_link ) . unwrap ( ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					         LinkOrder ::after_link ( & attached_programs . get ( "last" ) . unwrap ( ) . 1 ) . unwrap ( ) 
 
			
				
				
			
		
	
		
		
			
				
					
					     ) ;      let   ( before_default ,   _ )   =  
			
				
				
			
		
	
		
		
			
				
					
					     // TODO: Assert in position 3 at the end of the test.
          attach_program_with_linkorder ! ( LinkOrder ::before_program ( default_prog ) . unwrap ( ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					     attach_program_with_linkorder ! (      let   ( after_default ,   _ )   =  
			
				
				
			
		
	
		
		
			
				
					
					         "before_default" ,          attach_program_with_linkorder ! ( LinkOrder ::after_program ( default_prog ) . unwrap ( ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					         LinkOrder ::before_program ( 
 
			
				
				
			
		
	
		
		
			
				
					
					             TryInto ::< & SchedClassifier > ::try_into (      let   ( before_first ,   _ )   =   attach_program_with_linkorder ! ( LinkOrder ::before_program_id ( unsafe   {  
			
				
				
			
		
	
		
		
			
				
					
					                 attached_programs          ProgramId ::new ( first_prog . info ( ) . unwrap ( ) . id ( ) )  
			
				
				
			
		
	
		
		
			
				
					
					                     . get ( "default" )      } ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					                     . unwrap ( )      let   ( after_first ,   _ )   =   attach_program_with_linkorder ! ( LinkOrder ::after_program_id ( unsafe   {  
			
				
				
			
		
	
		
		
			
				
					
					                     . 0          ProgramId ::new ( first_prog . info ( ) . unwrap ( ) . id ( ) )  
			
				
				
			
		
	
		
		
			
				
					
					                     . program ( "tcx_next" )      } ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					                     . unwrap ( ) , 
 
			
				
				
			
		
	
		
		
			
				
					
					             )      let   expected_order   =   [  
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					         before_first  
			
		
	
		
		
			
				
					
					             . program ( "tcx_next" )  
			
		
	
		
		
			
				
					
					             . unwrap ( )              . unwrap ( )  
			
		
	
		
		
			
				
					
					         )              . info ( )  
			
				
				
			
		
	
		
		
			
				
					
					         . unwrap ( )  
			
		
	
		
		
			
				
					
					     ) ;  
			
		
	
		
		
			
				
					
					     // TODO: Assert in position 5 at the end of the test.
  
			
		
	
		
		
			
				
					
					     attach_program_with_linkorder ! (  
			
		
	
		
		
			
				
					
					         "after_default" ,  
			
		
	
		
		
			
				
					
					         LinkOrder ::after_program (  
			
		
	
		
		
			
				
					
					             TryInto ::< & SchedClassifier > ::try_into (  
			
		
	
		
		
			
				
					
					                 attached_programs  
			
		
	
		
		
			
				
					
					                     . get ( "default" )  
			
		
	
		
		
			
				
					
					                     . unwrap ( )  
			
		
	
		
		
			
				
					
					                     . 0  
			
		
	
		
		
			
				
					
					                     . program ( "tcx_next" )  
			
		
	
		
		
			
				
					
					                     . unwrap ( ) ,  
			
		
	
		
		
			
				
					
					             )  
			
		
	
		
		
	
		
		
			
				
					
					             . unwrap ( )              . unwrap ( )  
			
		
	
		
		
			
				
					
					         )              . id ( ) ,  
			
				
				
			
		
	
		
		
			
				
					
					         . unwrap ( )          first_prog . info ( ) . unwrap ( ) . id ( ) ,  
			
				
				
			
		
	
		
		
			
				
					
					     ) ;          after_first  
			
				
				
			
		
	
		
		
			
				
					
					     // TODO: Assert in position 0 at the end of the test.
              . program ( "tcx_next" )  
			
				
				
			
		
	
		
		
			
				
					
					     attach_program_with_linkorder ! (              . unwrap ( )  
			
				
				
			
		
	
		
		
			
				
					
					         "before_first" ,              . info ( )  
			
				
				
			
		
	
		
		
			
				
					
					         LinkOrder ::before_program_id ( unsafe   {              . unwrap ( )  
			
				
				
			
		
	
		
		
			
				
					
					             ProgramId ::new (              . id ( ) ,  
			
				
				
			
		
	
		
		
			
				
					
					                 TryInto ::< & SchedClassifier > ::try_into (          before_default  
			
				
				
			
		
	
		
		
			
				
					
					                     attached_programs              . program ( "tcx_next" )  
			
				
				
			
		
	
		
		
			
				
					
					                         . get ( "first" )              . unwrap ( )  
			
				
				
			
		
	
		
		
			
				
					
					                         . unwrap ( )              . info ( )  
			
				
				
			
		
	
		
		
			
				
					
					                         . 0              . unwrap ( )  
			
				
				
			
		
	
		
		
			
				
					
					                         . program ( "tcx_next" )              . id ( ) ,  
			
				
				
			
		
	
		
		
			
				
					
					                         . unwrap ( ) ,          default_prog . info ( ) . unwrap ( ) . id ( ) ,  
			
				
				
			
		
	
		
		
			
				
					
					                 )          after_default  
			
				
				
			
		
	
		
		
			
				
					
					                 . unwrap ( )              . program ( "tcx_next" )  
			
				
				
			
		
	
		
		
			
				
					
					                 . info ( )              . unwrap ( )  
			
				
				
			
		
	
		
		
			
				
					
					                 . unwrap ( )              . info ( )  
			
				
				
			
		
	
		
		
			
				
					
					                 . id ( ) ,              . unwrap ( )  
			
				
				
			
		
	
		
		
			
				
					
					             )              . id ( ) ,  
			
				
				
			
		
	
		
		
			
				
					
					         } )          before_last  
			
				
				
			
		
	
		
		
			
				
					
					     ) ;              . program ( "tcx_next" )  
			
				
				
			
		
	
		
		
			
				
					
					     // TODO: Assert in position 2 at the end of the test.
              . unwrap ( )  
			
				
				
			
		
	
		
		
			
				
					
					     attach_program_with_linkorder ! (              . info ( )  
			
				
				
			
		
	
		
		
			
				
					
					         "after_first" ,              . unwrap ( )  
			
				
				
			
		
	
		
		
			
				
					
					         LinkOrder ::after_program_id ( unsafe   {              . id ( ) ,  
			
				
				
			
		
	
		
		
			
				
					
					             ProgramId ::new (          last_prog . info ( ) . unwrap ( ) . id ( ) ,  
			
				
				
			
		
	
		
		
			
				
					
					                 TryInto ::< & SchedClassifier > ::try_into (          after_last . program ( "tcx_next" ) . unwrap ( ) . info ( ) . unwrap ( ) . id ( ) ,  
			
				
				
			
		
	
		
		
			
				
					
					                     attached_programs      ] ;  
			
				
				
			
		
	
		
		
			
				
					
					                         . get ( "first" ) 
 
			
				
				
			
		
	
		
		
			
				
					
					                         . unwrap ( )      let   ( revision ,   got_order )   =   SchedClassifier ::query_tcx ( "lo" ,   TcAttachType ::Ingress ) . unwrap ( ) ;  
			
				
				
			
		
	
		
		
			
				
					
					                         . 0      assert_eq! ( revision ,   ( expected_order . len ( )   +   1 )   as   u64 ) ;  
			
				
				
			
		
	
		
		
			
				
					
					                         . program ( "tcx_next" )      assert_eq! (  
			
				
				
			
		
	
		
		
			
				
					
					                         . unwrap ( ) ,          got_order . iter ( ) . map ( | p |   p . id ( ) ) . collect ::< Vec < _ > > ( ) ,  
			
				
				
			
		
	
		
		
			
				
					
					                 )          expected_order  
			
				
				
			
		
	
		
		
			
				
					
					                 . unwrap ( )  
			
		
	
		
		
			
				
					
					                 . info ( )  
			
		
	
		
		
			
				
					
					                 . unwrap ( )  
			
		
	
		
		
			
				
					
					                 . id ( ) ,  
			
		
	
		
		
			
				
					
					             )  
			
		
	
		
		
			
				
					
					         } )  
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					     ) ;      ) ;  
			
		
	
		
		
			
				
					
					     // TODO: Add code here to automatically verify the order after the API based
  
			
		
	
		
		
			
				
					
					     // on the BPF_PROG_QUERY syscall is implemented.
  
			
		
	
		
		
			
				
					
					} }