@@ -755,7 +755,7 @@ CxPlatDpRawInterfaceUpdateRules(
755755 .SubLayer = XDP_HOOK_INSPECT ,
756756 };
757757
758- const UINT32 Flags = 0 ; // TODO: support native/generic forced flags.
758+ const UINT32 Flags = XDP_CREATE_PROGRAM_FLAG_SHARE ; // TODO: support native/generic forced flags.
759759
760760 for (uint32_t i = 0 ; i < Interface -> QueueCount ; i ++ ) {
761761
@@ -798,9 +798,10 @@ CxPlatDpRawInterfaceUpdateRules(
798798
799799_IRQL_requires_max_ (PASSIVE_LEVEL )
800800void
801- CxPlatDpRawInterfaceAddRule (
801+ CxPlatDpRawInterfaceAddRules (
802802 _In_ XDP_INTERFACE * Interface ,
803- _In_ const XDP_RULE * NewRule
803+ _In_reads_ (Count ) const XDP_RULE * Rules ,
804+ _In_ uint8_t Count
804805 )
805806{
806807#pragma warning(push)
@@ -809,7 +810,7 @@ CxPlatDpRawInterfaceAddRule(
809810 CxPlatLockAcquire (& Interface -> RuleLock );
810811 // TODO - Don't always allocate a new array?
811812
812- if (Interface -> RuleCount + 1 == 0 ) {
813+ if (( uint32_t ) Interface -> RuleCount + ( uint32_t ) Count > UINT8_MAX ) {
813814 QuicTraceEvent (
814815 LibraryError ,
815816 "[ lib] ERROR, %s." ,
@@ -819,7 +820,7 @@ CxPlatDpRawInterfaceAddRule(
819820 }
820821
821822 const size_t OldSize = sizeof (XDP_RULE ) * (size_t )Interface -> RuleCount ;
822- const size_t NewSize = sizeof (XDP_RULE ) * ((size_t )Interface -> RuleCount + 1 );
823+ const size_t NewSize = sizeof (XDP_RULE ) * ((size_t )Interface -> RuleCount + Count );
823824
824825 XDP_RULE * NewRules = CxPlatAlloc (NewSize , RULE_TAG );
825826 if (NewRules == NULL ) {
@@ -835,8 +836,9 @@ CxPlatDpRawInterfaceAddRule(
835836 if (Interface -> RuleCount > 0 ) {
836837 memcpy (NewRules , Interface -> Rules , OldSize );
837838 }
838- NewRules [Interface -> RuleCount ] = * NewRule ;
839- Interface -> RuleCount ++ ;
839+ for (uint8_t i = 0 ; i < Count ; i ++ ) {
840+ NewRules [Interface -> RuleCount ++ ] = Rules [i ];
841+ }
840842
841843 if (Interface -> Rules != NULL ) {
842844 CxPlatFree (Interface -> Rules , RULE_TAG );
@@ -852,46 +854,62 @@ CxPlatDpRawInterfaceAddRule(
852854
853855_IRQL_requires_max_ (PASSIVE_LEVEL )
854856void
855- CxPlatDpRawInterfaceRemoveRule (
857+ CxPlatDpRawInterfaceRemoveRules (
856858 _In_ XDP_INTERFACE * Interface ,
857- _In_ const XDP_RULE * Rule
859+ _In_reads_ (Count ) const XDP_RULE * Rules ,
860+ _In_ uint8_t Count
858861 )
859862{
860863 CxPlatLockAcquire (& Interface -> RuleLock );
861864
862- for (uint8_t i = 0 ; i < Interface -> RuleCount ; i ++ ) {
863- if (Interface -> Rules [i ].Match != Rule -> Match ) {
864- continue ;
865- }
865+ BOOLEAN UpdateRules = FALSE;
866866
867- if (Rule -> Match == XDP_MATCH_UDP_DST ) {
868- if (Rule -> Pattern .Port != Interface -> Rules [i ].Pattern .Port ) {
867+ for (uint8_t j = 0 ; j < Count ; j ++ ) {
868+ for (uint8_t i = 0 ; i < Interface -> RuleCount ; i ++ ) {
869+ if (Interface -> Rules [i ].Match != Rules [j ].Match ) {
869870 continue ;
870871 }
871- } else if (Rule -> Match == XDP_MATCH_IPV4_UDP_TUPLE ) {
872- if (Rule -> Pattern .Tuple .DestinationPort != Interface -> Rules [i ].Pattern .Tuple .DestinationPort ||
873- Rule -> Pattern .Tuple .SourcePort != Interface -> Rules [i ].Pattern .Tuple .SourcePort ||
874- memcmp (& Rule -> Pattern .Tuple .DestinationAddress .Ipv4 , & Interface -> Rules [i ].Pattern .Tuple .DestinationAddress .Ipv4 , sizeof (IN_ADDR )) != 0 ||
875- memcmp (& Rule -> Pattern .Tuple .SourceAddress .Ipv4 , & Interface -> Rules [i ].Pattern .Tuple .SourceAddress .Ipv4 , sizeof (IN_ADDR )) != 0 ) {
876- continue ;
872+
873+ if (Rules [j ].Match == XDP_MATCH_UDP_DST ) {
874+ if (Rules [j ].Pattern .Port != Interface -> Rules [i ].Pattern .Port ) {
875+ continue ;
876+ }
877+ } else if (Rules [j ].Match == XDP_MATCH_QUIC_FLOW_SRC_CID || Rules [j ].Match == XDP_MATCH_QUIC_FLOW_DST_CID ) {
878+ if (Rules [j ].Pattern .QuicFlow .UdpPort != Interface -> Rules [i ].Pattern .QuicFlow .UdpPort ||
879+ Rules [j ].Pattern .QuicFlow .CidLength != Interface -> Rules [i ].Pattern .QuicFlow .CidLength ||
880+ Rules [j ].Pattern .QuicFlow .CidOffset != Interface -> Rules [i ].Pattern .QuicFlow .CidOffset ||
881+ memcmp (Rules [j ].Pattern .QuicFlow .CidData , Interface -> Rules [i ].Pattern .QuicFlow .CidData , Rules [j ].Pattern .QuicFlow .CidLength ) != 0 ) {
882+ continue ;
883+ }
884+ } else if (Rules [j ].Match == XDP_MATCH_IPV4_UDP_TUPLE ) {
885+ if (Rules [j ].Pattern .Tuple .DestinationPort != Interface -> Rules [i ].Pattern .Tuple .DestinationPort ||
886+ Rules [j ].Pattern .Tuple .SourcePort != Interface -> Rules [i ].Pattern .Tuple .SourcePort ||
887+ memcmp (& Rules [j ].Pattern .Tuple .DestinationAddress .Ipv4 , & Interface -> Rules [i ].Pattern .Tuple .DestinationAddress .Ipv4 , sizeof (IN_ADDR )) != 0 ||
888+ memcmp (& Rules [j ].Pattern .Tuple .SourceAddress .Ipv4 , & Interface -> Rules [i ].Pattern .Tuple .SourceAddress .Ipv4 , sizeof (IN_ADDR )) != 0 ) {
889+ continue ;
890+ }
891+ } else if (Rules [j ].Match == XDP_MATCH_IPV6_UDP_TUPLE ) {
892+ if (Rules [j ].Pattern .Tuple .DestinationPort != Interface -> Rules [i ].Pattern .Tuple .DestinationPort ||
893+ Rules [j ].Pattern .Tuple .SourcePort != Interface -> Rules [i ].Pattern .Tuple .SourcePort ||
894+ memcmp (& Rules [j ].Pattern .Tuple .DestinationAddress .Ipv6 , & Interface -> Rules [i ].Pattern .Tuple .DestinationAddress .Ipv6 , sizeof (IN6_ADDR )) != 0 ||
895+ memcmp (& Rules [j ].Pattern .Tuple .SourceAddress .Ipv6 , & Interface -> Rules [i ].Pattern .Tuple .SourceAddress .Ipv6 , sizeof (IN6_ADDR )) != 0 ) {
896+ continue ;
897+ }
898+ } else {
899+ CXPLAT_FRE_ASSERT (FALSE); // Should not be possible!
877900 }
878- } else if (Rule -> Match == XDP_MATCH_IPV6_UDP_TUPLE ) {
879- if (Rule -> Pattern .Tuple .DestinationPort != Interface -> Rules [i ].Pattern .Tuple .DestinationPort ||
880- Rule -> Pattern .Tuple .SourcePort != Interface -> Rules [i ].Pattern .Tuple .SourcePort ||
881- memcmp (& Rule -> Pattern .Tuple .DestinationAddress .Ipv6 , & Interface -> Rules [i ].Pattern .Tuple .DestinationAddress .Ipv6 , sizeof (IN6_ADDR )) != 0 ||
882- memcmp (& Rule -> Pattern .Tuple .SourceAddress .Ipv6 , & Interface -> Rules [i ].Pattern .Tuple .SourceAddress .Ipv6 , sizeof (IN6_ADDR )) != 0 ) {
883- continue ;
901+
902+ if (i < Interface -> RuleCount - 1 ) {
903+ memmove (& Interface -> Rules [i ], & Interface -> Rules [i + 1 ], sizeof (XDP_RULE ) * (Interface -> RuleCount - i - 1 ));
884904 }
885- } else {
886- CXPLAT_FRE_ASSERT (FALSE); // Should not be possible!
905+ Interface -> RuleCount -- ;
906+ UpdateRules = TRUE;
907+ break ;
887908 }
909+ }
888910
889- if (i < Interface -> RuleCount - 1 ) {
890- memmove (& Interface -> Rules [i ], & Interface -> Rules [i + 1 ], sizeof (XDP_RULE ) * (Interface -> RuleCount - i - 1 ));
891- }
892- Interface -> RuleCount -- ;
911+ if (UpdateRules ) {
893912 CxPlatDpRawInterfaceUpdateRules (Interface );
894- break ;
895913 }
896914
897915 CxPlatLockRelease (& Interface -> RuleLock );
@@ -1052,21 +1070,57 @@ CxPlatDpRawPlumbRulesOnSocket(
10521070 XDP_DATAPATH * Xdp = (XDP_DATAPATH * )Socket -> Datapath ;
10531071
10541072 if (Socket -> Wildcard ) {
1055- const XDP_RULE Rule = {
1056- .Match = XDP_MATCH_UDP_DST ,
1057- .Pattern .Port = Socket -> LocalAddress .Ipv4 .sin_port ,
1058- .Action = XDP_PROGRAM_ACTION_REDIRECT ,
1059- .Redirect .TargetType = XDP_REDIRECT_TARGET_TYPE_XSK ,
1060- .Redirect .Target = NULL ,
1061- };
10621073
1063- CXPLAT_LIST_ENTRY * Entry ;
1064- for (Entry = Xdp -> Interfaces .Flink ; Entry != & Xdp -> Interfaces ; Entry = Entry -> Flink ) {
1065- XDP_INTERFACE * Interface = CONTAINING_RECORD (Entry , XDP_INTERFACE , Link );
1066- if (IsCreated ) {
1067- CxPlatDpRawInterfaceAddRule (Interface , & Rule );
1068- } else {
1069- CxPlatDpRawInterfaceRemoveRule (Interface , & Rule );
1074+ if (Socket -> CibirIdLength ) {
1075+ XDP_RULE Rules [] = {
1076+ {
1077+ .Match = XDP_MATCH_QUIC_FLOW_SRC_CID ,
1078+ .Pattern .QuicFlow .UdpPort = Socket -> LocalAddress .Ipv4 .sin_port ,
1079+ .Pattern .QuicFlow .CidLength = Socket -> CibirIdLength ,
1080+ .Pattern .QuicFlow .CidOffset = Socket -> CibirIdOffsetSrc ,
1081+ .Action = XDP_PROGRAM_ACTION_REDIRECT ,
1082+ .Redirect .TargetType = XDP_REDIRECT_TARGET_TYPE_XSK ,
1083+ .Redirect .Target = NULL ,
1084+ },
1085+ {
1086+ .Match = XDP_MATCH_QUIC_FLOW_DST_CID ,
1087+ .Pattern .QuicFlow .UdpPort = Socket -> LocalAddress .Ipv4 .sin_port ,
1088+ .Pattern .QuicFlow .CidLength = Socket -> CibirIdLength ,
1089+ .Pattern .QuicFlow .CidOffset = Socket -> CibirIdOffsetDst ,
1090+ .Action = XDP_PROGRAM_ACTION_REDIRECT ,
1091+ .Redirect .TargetType = XDP_REDIRECT_TARGET_TYPE_XSK ,
1092+ .Redirect .Target = NULL ,
1093+ }
1094+ };
1095+ memcpy (Rules [0 ].Pattern .QuicFlow .CidData , Socket -> CibirId , Socket -> CibirIdLength );
1096+ memcpy (Rules [1 ].Pattern .QuicFlow .CidData , Socket -> CibirId , Socket -> CibirIdLength );
1097+
1098+ CXPLAT_LIST_ENTRY * Entry ;
1099+ for (Entry = Xdp -> Interfaces .Flink ; Entry != & Xdp -> Interfaces ; Entry = Entry -> Flink ) {
1100+ XDP_INTERFACE * Interface = CONTAINING_RECORD (Entry , XDP_INTERFACE , Link );
1101+ if (IsCreated ) {
1102+ CxPlatDpRawInterfaceAddRules (Interface , Rules , 2 );
1103+ } else {
1104+ CxPlatDpRawInterfaceRemoveRules (Interface , Rules , 2 );
1105+ }
1106+ }
1107+ } else {
1108+ const XDP_RULE Rule = {
1109+ .Match = XDP_MATCH_UDP_DST ,
1110+ .Pattern .Port = Socket -> LocalAddress .Ipv4 .sin_port ,
1111+ .Action = XDP_PROGRAM_ACTION_REDIRECT ,
1112+ .Redirect .TargetType = XDP_REDIRECT_TARGET_TYPE_XSK ,
1113+ .Redirect .Target = NULL ,
1114+ };
1115+
1116+ CXPLAT_LIST_ENTRY * Entry ;
1117+ for (Entry = Xdp -> Interfaces .Flink ; Entry != & Xdp -> Interfaces ; Entry = Entry -> Flink ) {
1118+ XDP_INTERFACE * Interface = CONTAINING_RECORD (Entry , XDP_INTERFACE , Link );
1119+ if (IsCreated ) {
1120+ CxPlatDpRawInterfaceAddRules (Interface , & Rule , 1 );
1121+ } else {
1122+ CxPlatDpRawInterfaceRemoveRules (Interface , & Rule , 1 );
1123+ }
10701124 }
10711125 }
10721126
@@ -1098,9 +1152,9 @@ CxPlatDpRawPlumbRulesOnSocket(
10981152 for (Entry = Xdp -> Interfaces .Flink ; Entry != & Xdp -> Interfaces ; Entry = Entry -> Flink ) {
10991153 XDP_INTERFACE * Interface = CONTAINING_RECORD (Entry , XDP_INTERFACE , Link );
11001154 if (IsCreated ) {
1101- CxPlatDpRawInterfaceAddRule (Interface , & Rule );
1155+ CxPlatDpRawInterfaceAddRules (Interface , & Rule , 1 );
11021156 } else {
1103- CxPlatDpRawInterfaceRemoveRule (Interface , & Rule );
1157+ CxPlatDpRawInterfaceRemoveRules (Interface , & Rule , 1 );
11041158 }
11051159 }
11061160 }
0 commit comments