@@ -17,6 +17,7 @@ use super::packet::InnerFlowId;
1717use super :: packet:: MblkFullParsed ;
1818use super :: packet:: MblkPacketData ;
1919use super :: packet:: Packet ;
20+ use super :: port:: PortBuilder ;
2021use super :: port:: Transforms ;
2122use super :: port:: meta:: ActionMeta ;
2223use super :: rule;
@@ -28,6 +29,8 @@ use super::rule::GenBtError;
2829use super :: rule:: HdrTransformError ;
2930use super :: rule:: Rule ;
3031use super :: rule:: ht_probe;
32+ use super :: stat:: StatTree ;
33+ use super :: stat:: TableStat ;
3134use crate :: ExecCtx ;
3235use crate :: LogLevel ;
3336use crate :: api:: DumpLayerResp ;
@@ -56,6 +59,7 @@ use opte_api::Direction;
5659use opte_api:: RuleDump ;
5760use opte_api:: RuleId ;
5861use opte_api:: RuleTableEntryDump ;
62+ use uuid:: Uuid ;
5963
6064#[ derive( Debug ) ]
6165pub enum LayerError {
@@ -353,8 +357,9 @@ pub enum EntryState {
353357/// reasonable to open this up to be any [`Action`], if such a use
354358/// case were to present itself. For now, we stay conservative, and
355359/// supply only what the current consumers need.
356- #[ derive( Copy , Clone , Debug ) ]
360+ #[ derive( Copy , Clone , Debug , Default ) ]
357361pub enum DefaultAction {
362+ #[ default]
358363 Allow ,
359364 StatefulAllow ,
360365 Deny ,
@@ -407,7 +412,7 @@ impl Display for ActionDescEntry {
407412///
408413/// This describes the actions a layer's rules can take as well as the
409414/// [`DefaultAction`] to take when a rule doesn't match.
410- #[ derive( Debug ) ]
415+ #[ derive( Debug , Default ) ]
411416pub struct LayerActions {
412417 /// The list of actions shared among the layer's rules. An action
413418 /// doesn't have to be shared, each rule is free to create its
@@ -419,9 +424,15 @@ pub struct LayerActions {
419424 /// direction.
420425 pub default_in : DefaultAction ,
421426
427+ /// The stats ID to attach to the default-in action.
428+ pub default_in_stat_id : Option < Uuid > ,
429+
422430 /// The default action to take if no rule matches in the outbound
423431 /// direction.
424432 pub default_out : DefaultAction ,
433+
434+ /// The stats ID to attach to the default-in action.
435+ pub default_out_stat_id : Option < Uuid > ,
425436}
426437
427438#[ derive( KStatProvider ) ]
@@ -503,8 +514,10 @@ pub struct Layer {
503514 actions : Vec < Action > ,
504515 default_in : DefaultAction ,
505516 default_in_hits : u64 ,
517+ default_in_stat : Arc < TableStat > ,
506518 default_out : DefaultAction ,
507519 default_out_hits : u64 ,
520+ default_out_stat : Arc < TableStat > ,
508521 ft : LayerFlowTable ,
509522 ft_cstr : CString ,
510523 rules_in : RuleTable ,
@@ -518,15 +531,20 @@ impl Layer {
518531 self . actions . get ( idx) . cloned ( )
519532 }
520533
521- pub fn add_rule ( & mut self , dir : Direction , rule : Rule < Finalized > ) {
534+ pub fn add_rule (
535+ & mut self ,
536+ dir : Direction ,
537+ rule : Rule < Finalized > ,
538+ stats : & mut StatTree ,
539+ ) {
522540 match dir {
523541 Direction :: Out => {
524- self . rules_out . add ( rule) ;
542+ self . rules_out . add ( rule, stats ) ;
525543 self . stats . vals . out_rules += 1 ;
526544 }
527545
528546 Direction :: In => {
529- self . rules_in . add ( rule) ;
547+ self . rules_in . add ( rule, stats ) ;
530548 self . stats . vals . in_rules += 1 ;
531549 }
532550 }
@@ -737,18 +755,24 @@ impl Layer {
737755
738756 pub fn new (
739757 name : & ' static str ,
740- port : & str ,
758+ port : & mut PortBuilder ,
741759 actions : LayerActions ,
742760 ft_limit : NonZeroU32 ,
743761 ) -> Self {
744- let port_c = CString :: new ( port) . unwrap ( ) ;
762+ let stats = port. stats_mut ( ) ;
763+ let default_in_stat = stats. root ( actions. default_in_stat_id ) ;
764+ let default_out_stat = stats. root ( actions. default_out_stat_id ) ;
765+
766+ let port_name = port. name ( ) ;
767+
768+ let port_c = CString :: new ( port_name) . unwrap ( ) ;
745769 let name_c = CString :: new ( name) . unwrap ( ) ;
746770
747771 // Unwrap: We know this is fine because the stat names are
748772 // generated from the LayerStats structure.
749773 let stats = KStatNamed :: new (
750774 "xde" ,
751- & format ! ( "{}_{}" , port , name) ,
775+ & format ! ( "{}_{}" , port_name , name) ,
752776 LayerStats :: new ( ) ,
753777 )
754778 . unwrap ( ) ;
@@ -759,15 +783,17 @@ impl Layer {
759783 actions : actions. actions ,
760784 default_in : actions. default_in ,
761785 default_in_hits : 0 ,
786+ default_in_stat,
762787 default_out : actions. default_out ,
763788 default_out_hits : 0 ,
789+ default_out_stat,
764790 name,
765791 name_c,
766792 port_c,
767- ft : LayerFlowTable :: new ( port , name, ft_limit) ,
793+ ft : LayerFlowTable :: new ( port_name , name, ft_limit) ,
768794 ft_cstr : CString :: new ( format ! ( "ft-{}" , name) ) . unwrap ( ) ,
769- rules_in : RuleTable :: new ( port , name, Direction :: In ) ,
770- rules_out : RuleTable :: new ( port , name, Direction :: Out ) ,
795+ rules_in : RuleTable :: new ( port_name , name, Direction :: In ) ,
796+ rules_out : RuleTable :: new ( port_name , name, Direction :: Out ) ,
771797 rt_cstr : CString :: new ( format ! ( "rt-{}" , name) ) . unwrap ( ) ,
772798 stats,
773799 }
@@ -795,12 +821,12 @@ impl Layer {
795821 xforms : & mut Transforms ,
796822 ameta : & mut ActionMeta ,
797823 ) -> result:: Result < LayerResult , LayerError > {
798- use Direction :: * ;
799824 let flow_before = * pkt. flow ( ) ;
800825 self . layer_process_entry_probe ( dir, pkt. flow ( ) ) ;
826+ pkt. meta_mut ( ) . stats . new_layer ( ) ;
801827 let res = match dir {
802- Out => self . process_out ( ectx, pkt, xforms, ameta) ,
803- In => self . process_in ( ectx, pkt, xforms, ameta) ,
828+ Direction :: Out => self . process_out ( ectx, pkt, xforms, ameta) ,
829+ Direction :: In => self . process_in ( ectx, pkt, xforms, ameta) ,
804830 } ;
805831 self . layer_process_return_probe ( dir, & flow_before, pkt. flow ( ) , & res) ;
806832 res
@@ -888,15 +914,21 @@ impl Layer {
888914 self . stats . vals . in_lft_miss += 1 ;
889915 let rule = self . rules_in . find_match ( pkt. flow ( ) , pkt. meta ( ) , ameta) ;
890916
891- let action = if let Some ( rule) = rule {
917+ let ( action, stat ) = if let Some ( rule) = rule {
892918 self . stats . vals . in_rule_match += 1 ;
893- rule. action ( )
919+ ( rule. rule . action ( ) , rule . stat . clone ( ) )
894920 } else {
895921 self . stats . vals . in_rule_nomatch += 1 ;
896922 self . default_in_hits += 1 ;
897- self . default_in . into ( )
923+ ( self . default_in . into ( ) , self . default_in_stat . clone ( ) )
898924 } ;
899925
926+ // No LFT to account for.
927+ let mut stat = Some ( stat) ;
928+ if !matches ! ( action, Action :: StatefulAllow | Action :: Stateful ( _) ) {
929+ pkt. meta_mut ( ) . stats . push ( stat. take ( ) . unwrap ( ) ) ;
930+ }
931+
900932 match action {
901933 Action :: Allow => Ok ( LayerResult :: Allow ) ,
902934
@@ -909,6 +941,8 @@ impl Layer {
909941 } ) ;
910942 }
911943
944+ // TODO: how on earth are we plumbing StatTree into here??
945+
912946 // The outbound flow ID mirrors the inbound. Remember,
913947 // the "top" of layer represents how the client sees
914948 // the traffic, and the "bottom" of the layer
@@ -1019,6 +1053,8 @@ impl Layer {
10191053 } ) ;
10201054 }
10211055
1056+ // TODO: how on earth are we plumbing StatTree into here??
1057+
10221058 let desc = match action. gen_desc ( pkt. flow ( ) , pkt, ameta) {
10231059 Ok ( aord) => match aord {
10241060 AllowOrDeny :: Allow ( desc) => desc,
@@ -1175,15 +1211,21 @@ impl Layer {
11751211 self . stats . vals . out_lft_miss += 1 ;
11761212 let rule = self . rules_out . find_match ( pkt. flow ( ) , pkt. meta ( ) , ameta) ;
11771213
1178- let action = if let Some ( rule) = rule {
1214+ let ( action, stat ) = if let Some ( rule) = rule {
11791215 self . stats . vals . out_rule_match += 1 ;
1180- rule. action ( )
1216+ ( rule. rule . action ( ) , rule . stat . clone ( ) )
11811217 } else {
11821218 self . stats . vals . out_rule_nomatch += 1 ;
11831219 self . default_out_hits += 1 ;
1184- self . default_out . into ( )
1220+ ( self . default_out . into ( ) , self . default_out_stat . clone ( ) )
11851221 } ;
11861222
1223+ // No LFT to account for.
1224+ let mut stat = Some ( stat) ;
1225+ if !matches ! ( action, Action :: StatefulAllow | Action :: Stateful ( _) ) {
1226+ pkt. meta_mut ( ) . stats . push ( stat. take ( ) . unwrap ( ) ) ;
1227+ }
1228+
11871229 match action {
11881230 Action :: Allow => Ok ( LayerResult :: Allow ) ,
11891231
@@ -1196,6 +1238,8 @@ impl Layer {
11961238 } ) ;
11971239 }
11981240
1241+ // TODO: how on earth are we plumbing StatTree into here??
1242+
11991243 // The inbound flow ID must be calculated _after_ the
12001244 // header transformation. Remember, the "top"
12011245 // (outbound) of layer represents how the client sees
@@ -1308,6 +1352,8 @@ impl Layer {
13081352 } ) ;
13091353 }
13101354
1355+ // TODO: how on earth are we plumbing StatTree into here??
1356+
13111357 let desc = match action. gen_desc ( pkt. flow ( ) , pkt, ameta) {
13121358 Ok ( aord) => match aord {
13131359 AllowOrDeny :: Allow ( desc) => desc,
@@ -1492,9 +1538,10 @@ impl Layer {
14921538 & mut self ,
14931539 in_rules : Vec < Rule < Finalized > > ,
14941540 out_rules : Vec < Rule < Finalized > > ,
1541+ stats : & mut StatTree ,
14951542 ) {
14961543 self . ft . clear ( ) ;
1497- self . set_rules_core ( in_rules, out_rules) ;
1544+ self . set_rules_core ( in_rules, out_rules, stats ) ;
14981545 }
14991546
15001547 /// Set all rules at once without clearing the flow table.
@@ -1505,18 +1552,20 @@ impl Layer {
15051552 & mut self ,
15061553 in_rules : Vec < Rule < Finalized > > ,
15071554 out_rules : Vec < Rule < Finalized > > ,
1555+ stats : & mut StatTree ,
15081556 ) {
15091557 self . ft . mark_dirty ( ) ;
1510- self . set_rules_core ( in_rules, out_rules) ;
1558+ self . set_rules_core ( in_rules, out_rules, stats ) ;
15111559 }
15121560
15131561 fn set_rules_core (
15141562 & mut self ,
15151563 in_rules : Vec < Rule < Finalized > > ,
15161564 out_rules : Vec < Rule < Finalized > > ,
1565+ stats : & mut StatTree ,
15171566 ) {
1518- self . rules_in . set_rules ( in_rules) ;
1519- self . rules_out . set_rules ( out_rules) ;
1567+ self . rules_in . set_rules ( in_rules, stats ) ;
1568+ self . rules_out . set_rules ( out_rules, stats ) ;
15201569 self . stats . vals . set_rules_called += 1 ;
15211570 self . stats . vals . in_rules . set ( self . rules_in . num_rules ( ) as u64 ) ;
15221571 self . stats . vals . out_rules . set ( self . rules_out . num_rules ( ) as u64 ) ;
@@ -1532,6 +1581,7 @@ struct RuleTableEntry {
15321581 id : RuleId ,
15331582 hits : u64 ,
15341583 rule : Rule < rule:: Finalized > ,
1584+ stat : Arc < TableStat > ,
15351585}
15361586
15371587impl From < & RuleTableEntry > for RuleTableEntryDump {
@@ -1561,15 +1611,18 @@ pub enum RuleRemoveErr {
15611611}
15621612
15631613impl RuleTable {
1564- fn add ( & mut self , rule : Rule < rule:: Finalized > ) {
1614+ fn add ( & mut self , rule : Rule < rule:: Finalized > , stats : & mut StatTree ) {
1615+ let stat = stats. root ( rule. stat_id ( ) . copied ( ) ) ;
15651616 match self . find_pos ( & rule) {
15661617 RulePlace :: End => {
1567- let rte = RuleTableEntry { id : self . next_id , hits : 0 , rule } ;
1618+ let rte =
1619+ RuleTableEntry { id : self . next_id , hits : 0 , rule, stat } ;
15681620 self . rules . push ( rte) ;
15691621 }
15701622
15711623 RulePlace :: Insert ( idx) => {
1572- let rte = RuleTableEntry { id : self . next_id , hits : 0 , rule } ;
1624+ let rte =
1625+ RuleTableEntry { id : self . next_id , hits : 0 , rule, stat } ;
15731626 self . rules . insert ( idx, rte) ;
15741627 }
15751628 }
@@ -1589,7 +1642,7 @@ impl RuleTable {
15891642 ifid : & InnerFlowId ,
15901643 pmeta : & MblkPacketData ,
15911644 ameta : & ActionMeta ,
1592- ) -> Option < & Rule < rule :: Finalized > > {
1645+ ) -> Option < & RuleTableEntry > {
15931646 for rte in self . rules . iter_mut ( ) {
15941647 if rte. rule . is_match ( pmeta, ameta) {
15951648 rte. hits += 1 ;
@@ -1600,7 +1653,7 @@ impl RuleTable {
16001653 ifid,
16011654 & rte. rule ,
16021655 ) ;
1603- return Some ( & rte. rule ) ;
1656+ return Some ( rte) ;
16041657 }
16051658 }
16061659
@@ -1738,10 +1791,14 @@ impl RuleTable {
17381791 }
17391792 }
17401793
1741- pub fn set_rules ( & mut self , new_rules : Vec < Rule < rule:: Finalized > > ) {
1794+ pub fn set_rules (
1795+ & mut self ,
1796+ new_rules : Vec < Rule < rule:: Finalized > > ,
1797+ stats : & mut StatTree ,
1798+ ) {
17421799 self . rules . clear ( ) ;
17431800 for r in new_rules {
1744- self . add ( r) ;
1801+ self . add ( r, stats ) ;
17451802 }
17461803 }
17471804}
@@ -1825,6 +1882,7 @@ mod test {
18251882 use crate :: engine:: predicate:: Predicate ;
18261883 use crate :: engine:: rule;
18271884
1885+ let mut stats = StatTree :: default ( ) ;
18281886 let mut rule_table = RuleTable :: new ( "port" , "test" , Direction :: Out ) ;
18291887 let mut rule = Rule :: new (
18301888 1 ,
@@ -1835,7 +1893,7 @@ mod test {
18351893 Ipv4AddrMatch :: Prefix ( cidr) ,
18361894 ] ) ) ;
18371895
1838- rule_table. add ( rule. finalize ( ) ) ;
1896+ rule_table. add ( rule. finalize ( ) , & mut stats ) ;
18391897
18401898 let mut test_pkt = MsgBlk :: new_ethernet_pkt ( (
18411899 Ethernet { ethertype : Ethertype :: IPV4 , ..Default :: default ( ) } ,
0 commit comments