@@ -23,6 +23,12 @@ pub struct Table {
2323}
2424
2525// soft-npu table names
26+ // Route tables are idx-only in sidecar-lite; route_ttl_is_1 is ignored here.
27+ // TODO: remove compat once sidecar-lite updates route keys/actions:
28+ // - p4/sidecar-lite.p4: add route_ttl_is_1 to route table keys and add
29+ // ttl_exceeded actions; set ingress.route_ttl_is_1 in router.
30+ // - p4/softnpu.p4: add route_ttl_is_1 to ingress metadata.
31+ // - scadm + softnpu tests: encode/decode idx + ttl in route keys.
2632const ROUTER_V4_RT : & str = "ingress.router.v4_route.rtr" ;
2733const ROUTER_V4_IDX : & str = "ingress.router.v4_idx.rtr" ;
2834const ROUTER_V6_RT : & str = "ingress.router.v6_route.rtr" ;
@@ -44,16 +50,19 @@ const _PROXY_ARP: &str = "ingress.pxarp.proxy_arp";
4450const SWITCH_ADDR4 : & str = "pipe.Ingress.filter.switch_ipv4_addr" ;
4551const SWITCH_ADDR6 : & str = "pipe.Ingress.filter.switch_ipv6_addr" ;
4652const ROUTER4_LOOKUP_RT : & str =
47- "pipe.Ingress.l3_router.Router4 .lookup_idx.route" ;
53+ "pipe.Ingress.l3_router.router4 .lookup_idx.route" ;
4854const ROUTER4_LOOKUP_IDX : & str =
49- "pipe.Ingress.l3_router.Router4 .lookup_idx.lookup" ;
55+ "pipe.Ingress.l3_router.router4 .lookup_idx.lookup" ;
5056const ROUTER6_LOOKUP_RT : & str =
51- "pipe.Ingress.l3_router.Router6 .lookup_idx.route" ;
57+ "pipe.Ingress.l3_router.router6 .lookup_idx.route" ;
5258const ROUTER6_LOOKUP_IDX : & str =
53- "pipe.Ingress.l3_router.Router6 .lookup_idx.lookup" ;
59+ "pipe.Ingress.l3_router.router6 .lookup_idx.lookup" ;
5460const NDP : & str = "pipe.Ingress.l3_router.Ndp.tbl" ;
5561const ARP : & str = "pipe.Ingress.l3_router.Arp.tbl" ;
56- const DPD_MAC_REWRITE : & str = "pipe.Ingress.mac_rewrite.mac_rewrite" ;
62+ const DPD_UNICAST_MAC_REWRITE : & str =
63+ "pipe.Egress.unicast_mac_rewrite.mac_rewrite" ;
64+ #[ cfg( feature = "multicast" ) ]
65+ const DPD_MCAST_MAC_REWRITE : & str = "pipe.Egress.mcast_mac_rewrite.mac_rewrite" ;
5766const NAT_INGRESS4 : & str = "pipe.Ingress.nat_ingress.ingress_ipv4" ;
5867const NAT_INGRESS6 : & str = "pipe.Ingress.nat_ingress.ingress_ipv6" ;
5968const ATTACHED_SUBNET_INGRESS4 : & str =
@@ -85,8 +94,12 @@ impl TableOps<Handle> for Table {
8594 SWITCH_ADDR6 => ( Some ( LOCAL_V6 . into ( ) ) , Some ( SWITCH_ADDR6 . into ( ) ) ) ,
8695 NDP => ( Some ( RESOLVER_V6 . into ( ) ) , Some ( NDP . into ( ) ) ) ,
8796 ARP => ( Some ( RESOLVER_V4 . into ( ) ) , Some ( ARP . into ( ) ) ) ,
88- DPD_MAC_REWRITE => {
89- ( Some ( MAC_REWRITE . into ( ) ) , Some ( DPD_MAC_REWRITE . into ( ) ) )
97+ DPD_UNICAST_MAC_REWRITE => {
98+ ( Some ( MAC_REWRITE . into ( ) ) , Some ( DPD_UNICAST_MAC_REWRITE . into ( ) ) )
99+ }
100+ #[ cfg( feature = "multicast" ) ]
101+ DPD_MCAST_MAC_REWRITE => {
102+ ( Some ( MAC_REWRITE . into ( ) ) , Some ( DPD_MCAST_MAC_REWRITE . into ( ) ) )
90103 }
91104 NAT_INGRESS4 => ( Some ( NAT_V4 . into ( ) ) , Some ( NAT_INGRESS4 . into ( ) ) ) ,
92105 NAT_INGRESS6 => ( Some ( NAT_V6 . into ( ) ) , Some ( NAT_INGRESS6 . into ( ) ) ) ,
@@ -135,9 +148,22 @@ impl TableOps<Handle> for Table {
135148 let action_data = data. action_to_ir ( ) . unwrap ( ) ;
136149
137150 trace ! ( hdl. log, "entry_add called" ) ;
138- trace ! ( hdl. log, "table: {}" , table) ;
139- trace ! ( hdl. log, "match_data:\n {:#?}" , match_data) ;
140- trace ! ( hdl. log, "action_data:\n {:#?}" , action_data) ;
151+ trace ! ( hdl. log, "table: {table}" ) ;
152+ trace ! ( hdl. log, "match_data:\n {match_data:#?}" ) ;
153+ trace ! ( hdl. log, "action_data:\n {action_data:#?}" ) ;
154+
155+ let is_route_table =
156+ matches ! ( dpd_table. as_str( ) , ROUTER4_LOOKUP_RT | ROUTER6_LOOKUP_RT ) ;
157+ if is_route_table {
158+ if route_ttl_is_1 ( & match_data. fields ) {
159+ trace ! ( hdl. log, "skipping ttl==1 route entry for {dpd_table}" ) ;
160+ return Ok ( ( ) ) ;
161+ }
162+ if action_data. action == "ttl_exceeded" {
163+ trace ! ( hdl. log, "skipping ttl_exceeded action for {dpd_table}" ) ;
164+ return Ok ( ( ) ) ;
165+ }
166+ }
141167
142168 let keyset_data = keyset_data ( match_data. fields , & table) ;
143169
@@ -440,7 +466,23 @@ impl TableOps<Handle> for Table {
440466 }
441467 ( "rewrite_dst" , params)
442468 }
443- ( DPD_MAC_REWRITE , "rewrite" ) => {
469+ ( DPD_UNICAST_MAC_REWRITE , "rewrite" ) => {
470+ let mut params = Vec :: new ( ) ;
471+ for arg in action_data. args {
472+ match arg. value {
473+ ValueTypes :: U64 ( v) => {
474+ let mac = v. to_le_bytes ( ) ;
475+ params. extend_from_slice ( & mac[ 0 ..6 ] ) ;
476+ }
477+ ValueTypes :: Ptr ( v) => {
478+ params. extend_from_slice ( v. as_slice ( ) ) ;
479+ }
480+ }
481+ }
482+ ( "rewrite" , params)
483+ }
484+ #[ cfg( feature = "multicast" ) ]
485+ ( DPD_MCAST_MAC_REWRITE , "rewrite" ) => {
444486 let mut params = Vec :: new ( ) ;
445487 for arg in action_data. args {
446488 match arg. value {
@@ -545,10 +587,10 @@ impl TableOps<Handle> for Table {
545587 } ;
546588 let action = action. to_string ( ) ;
547589 trace ! ( hdl. log, "sending request to softnpu" ) ;
548- trace ! ( hdl. log, "table: {}" , table ) ;
549- trace ! ( hdl. log, "action: {:#?}" , action ) ;
550- trace ! ( hdl. log, "keyset_data:\n {:#?}" , keyset_data ) ;
551- trace ! ( hdl. log, "parameter_data:\n {:#?}" , parameter_data ) ;
590+ trace ! ( hdl. log, "table: {table}" ) ;
591+ trace ! ( hdl. log, "action: {action :#?}" ) ;
592+ trace ! ( hdl. log, "keyset_data:\n {keyset_data :#?}" ) ;
593+ trace ! ( hdl. log, "parameter_data:\n {parameter_data :#?}" ) ;
552594
553595 let msg = ManagementRequest :: TableAdd ( TableAdd {
554596 table,
@@ -576,9 +618,9 @@ impl TableOps<Handle> for Table {
576618 let action_data = data. action_to_ir ( ) . unwrap ( ) ;
577619
578620 trace ! ( hdl. log, "entry_update called" ) ;
579- trace ! ( hdl. log, "table: {}" , table ) ;
580- trace ! ( hdl. log, "match_data:\n {:#?}" , match_data ) ;
581- trace ! ( hdl. log, "action_data:\n {:#?}" , action_data ) ;
621+ trace ! ( hdl. log, "table: {table}" ) ;
622+ trace ! ( hdl. log, "match_data:\n {match_data :#?}" ) ;
623+ trace ! ( hdl. log, "action_data:\n {action_data :#?}" ) ;
582624
583625 //TODO implement in softnpu
584626 Ok ( ( ) )
@@ -593,17 +635,31 @@ impl TableOps<Handle> for Table {
593635 None => return Ok ( ( ) ) ,
594636 Some ( id) => id. clone ( ) ,
595637 } ;
638+ let dpd_table = match & self . dpd_id {
639+ None => return Ok ( ( ) ) ,
640+ Some ( id) => id. clone ( ) ,
641+ } ;
596642 let match_data = key. key_to_ir ( ) . unwrap ( ) ;
597643
598644 trace ! ( hdl. log, "entry_del called" ) ;
599- trace ! ( hdl. log, "table: {}" , table) ;
600- trace ! ( hdl. log, "match_data:\n {:#?}" , match_data) ;
645+ trace ! ( hdl. log, "table: {table}" ) ;
646+ trace ! ( hdl. log, "match_data:\n {match_data:#?}" ) ;
647+
648+ let is_route_table =
649+ matches ! ( dpd_table. as_str( ) , ROUTER4_LOOKUP_RT | ROUTER6_LOOKUP_RT ) ;
650+ if is_route_table && route_ttl_is_1 ( & match_data. fields ) {
651+ trace ! (
652+ hdl. log,
653+ "skipping ttl==1 route entry delete for {dpd_table}"
654+ ) ;
655+ return Ok ( ( ) ) ;
656+ }
601657
602658 let keyset_data = keyset_data ( match_data. fields , & table) ;
603659
604660 trace ! ( hdl. log, "sending request to softnpu" ) ;
605- trace ! ( hdl. log, "table: {}" , table ) ;
606- trace ! ( hdl. log, "keyset_data:\n {:#?}" , keyset_data ) ;
661+ trace ! ( hdl. log, "table: {table}" ) ;
662+ trace ! ( hdl. log, "keyset_data:\n {keyset_data :#?}" ) ;
607663
608664 let msg =
609665 ManagementRequest :: TableRemove ( TableRemove { keyset_data, table } ) ;
@@ -641,12 +697,12 @@ fn keyset_data(match_data: Vec<MatchEntryField>, table: &str) -> Vec<u8> {
641697 let mut data: Vec < u8 > = Vec :: new ( ) ;
642698 match table {
643699 RESOLVER_V4 => {
644- // "nexthop_ipv4 " => bit<32>
700+ // "nexthop " => bit<32>
645701 serialize_value_type ( & x, & mut data) ;
646702 keyset_data. extend_from_slice ( & data[ ..4 ] ) ;
647703 }
648704 RESOLVER_V6 => {
649- // "nexthop_ipv4 " => bit<128>
705+ // "nexthop " => bit<128>
650706 let mut buf = Vec :: new ( ) ;
651707 serialize_value_type ( & x, & mut buf) ;
652708 buf. reverse ( ) ;
@@ -656,10 +712,12 @@ fn keyset_data(match_data: Vec<MatchEntryField>, table: &str) -> Vec<u8> {
656712 serialize_value_type ( & x, & mut data) ;
657713 keyset_data. extend_from_slice ( & data[ ..2 ] ) ;
658714 }
659- ROUTER_V4_RT => {
660- // "idx" => exact => bit<16>
661- serialize_value_type ( & x, & mut data) ;
662- keyset_data. extend_from_slice ( & data[ ..2 ] ) ;
715+ ROUTER_V4_RT | ROUTER_V6_RT => {
716+ // sidecar-lite route keys are idx-only.
717+ if m. name == "idx" {
718+ serialize_value_type ( & x, & mut data) ;
719+ keyset_data. extend_from_slice ( & data[ ..2 ] ) ;
720+ }
663721 }
664722 NAT_V4 => {
665723 // "dst_addr" => hdr.ipv4.dst: exact => bit<32>
@@ -749,3 +807,18 @@ fn serialize_value_type_be(x: &ValueTypes, data: &mut Vec<u8>) {
749807 }
750808 }
751809}
810+
811+ fn route_ttl_is_1 ( fields : & [ MatchEntryField ] ) -> bool {
812+ fields. iter ( ) . any ( |field| {
813+ if field. name != "route_ttl_is_1" {
814+ return false ;
815+ }
816+ match & field. value {
817+ MatchEntryValue :: Value ( ValueTypes :: U64 ( v) ) => * v != 0 ,
818+ MatchEntryValue :: Value ( ValueTypes :: Ptr ( v) ) => {
819+ v. first ( ) . is_some_and ( |b| * b != 0 )
820+ }
821+ _ => false ,
822+ }
823+ } )
824+ }
0 commit comments