Merge "Extend QosFilter address matching function" into main

This commit is contained in:
Sewook Seo 2025-05-09 01:02:33 -07:00 • committed by Android (Google) Code Review
commit ceb29e6cdf
7 changed files with 169 additions and 32 deletions

View file

@ -39,6 +39,11 @@ java_aconfig_library {
],
}
// This library MUST NOT be available to platform. This is because if the
// platform depends on a flag, it will not be able to delete that flag until
// that platform version is no longer supported by mainline. Additionally,
// there is no any safety mechanism that prevents the module from
// deleting the flag by mistake, regressing on previous platform versions.
java_aconfig_library {
name: "com.android.net.flags-aconfig-java-export",
aconfig_declarations: "com.android.net.flags-aconfig",

View file

@ -191,3 +191,11 @@ flag {
bug: "397536853"
is_fixed_read_only: true
}
flag {
name: "qos_filter_ip_range_matching"
namespace: "android_core_networking"
description: "Flag for API to provide IP address range based QoS socket matching."
bug: "406146808"
is_fixed_read_only: true
}

View file

@ -433,8 +433,10 @@ package android.net {
public abstract class QosFilter {
method @NonNull public abstract android.net.Network getNetwork();
method public abstract boolean matchesLocalAddress(@NonNull java.net.InetAddress, int, int);
method @FlaggedApi("com.android.net.flags.qos_filter_ip_range_matching") public abstract boolean matchesLocalPrefix(@NonNull android.net.IpPrefix, int, int);
method public boolean matchesProtocol(int);
method public abstract boolean matchesRemoteAddress(@NonNull java.net.InetAddress, int, int);
method @FlaggedApi("com.android.net.flags.qos_filter_ip_range_matching") public abstract boolean matchesRemotePrefix(@NonNull android.net.IpPrefix, int, int);
}
public final class QosSession implements android.os.Parcelable {

View file

@ -16,9 +16,12 @@
package android.net;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import com.android.net.flags.Flags;
import java.net.InetAddress;
/**
@ -93,6 +96,38 @@ public abstract class QosFilter {
public abstract boolean matchesRemoteAddress(@NonNull InetAddress address,
int startPort, int endPort);
/**
* Determines whether or not the parameters will be matched with prefix length, source address
* and port.
*
* @param ipPrefix the UE side IP address and prefix length included in IP packet filter set of
* a QoS flow assigned on {@link Network}.
* @param startPort the start of UE side port range included in IP packet filter set of a QoS
* flow assigned on {@link Network}.
* @param endPort the end of UE side port range included in IP packet filter set of a QoS flow
* assigned on {@link Network}.
* @return whether the parameters match the UE side address and port of the filter
*/
@FlaggedApi(Flags.FLAG_QOS_FILTER_IP_RANGE_MATCHING)
public abstract boolean matchesLocalPrefix(
@NonNull IpPrefix ipPrefix, int startPort, int endPort);
/**
* Determines whether or not the parameters will be matched with prefix length, remote address
* and port.
*
* @param ipPrefix the remote IP address and prefix length included in IP packet filter set of a
* QoS flow assigned on {@link Network}.
* @param startPort the start of remote port range included in IP packet filter set of a QoS
* flow assigned on {@link Network}.
* @param endPort the end of the remote range included in IP packet filter set of a QoS flow
* assigned on {@link Network}.
* @return whether the parameters match the remote address and port of the filter
*/
@FlaggedApi(Flags.FLAG_QOS_FILTER_IP_RANGE_MATCHING)
public abstract boolean matchesRemotePrefix(
@NonNull IpPrefix ipPrefix, int startPort, int endPort);
/**
* Determines whether or not the parameter will be matched with this filter.
*

View file

@ -36,6 +36,7 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import java.io.FileDescriptor;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
@ -179,10 +180,11 @@ public class QosSocketFilter extends QosFilter {
@Override
public boolean matchesLocalAddress(@NonNull final InetAddress address, final int startPort,
final int endPort) {
if (mQosSocketInfo.getLocalSocketAddress() == null) {
return false;
}
return matchesAddress(mQosSocketInfo.getLocalSocketAddress(), address, startPort,
return matchesLocalPrefix(
address instanceof Inet4Address
? new IpPrefix(address, 32)
: new IpPrefix(address, 128),
startPort,
endPort);
}
@ -192,11 +194,33 @@ public class QosSocketFilter extends QosFilter {
@Override
public boolean matchesRemoteAddress(@NonNull final InetAddress address, final int startPort,
final int endPort) {
return matchesRemotePrefix(
address instanceof Inet4Address
? new IpPrefix(address, 32)
: new IpPrefix(address, 128),
startPort,
endPort);
}
/** {@inheritDoc} */
@Override
public boolean matchesLocalPrefix(
@NonNull final IpPrefix ipPrefix, final int startPort, final int endPort) {
if (mQosSocketInfo.getLocalSocketAddress() == null) {
return false;
}
return matchesAddress(mQosSocketInfo.getLocalSocketAddress(), ipPrefix, startPort, endPort);
}
/** {@inheritDoc} */
@Override
public boolean matchesRemotePrefix(
@NonNull final IpPrefix ipPrefix, final int startPort, final int endPort) {
if (mQosSocketInfo.getRemoteSocketAddress() == null) {
return false;
}
return matchesAddress(mQosSocketInfo.getRemoteSocketAddress(), address, startPort,
endPort);
return matchesAddress(
mQosSocketInfo.getRemoteSocketAddress(), ipPrefix, startPort, endPort);
}
/**
@ -212,25 +236,27 @@ public class QosSocketFilter extends QosFilter {
}
/**
* Called from {@link QosSocketFilter#matchesLocalAddress(InetAddress, int, int)}
* and {@link QosSocketFilter#matchesRemoteAddress(InetAddress, int, int)} with the
* filterSocketAddress coming from {@link QosSocketInfo#getLocalSocketAddress()}.
* <p>
* This method exists for testing purposes since {@link QosSocketInfo} couldn't be mocked
* due to being final.
* Called from {@link QosSocketFilter#matchesLocalPrefix(IpPrefix, int, int)} and {@link
* QosSocketFilter#matchesRemotePrefix(IpPrefix, int, int)} with the filterSocketAddress coming
* from {@link QosSocketInfo#getLocalSocketAddress()}.
*
* <p>This method exists for testing purposes since {@link QosSocketInfo} couldn't be mocked due
* to being final.
*
* @param filterSocketAddress the socket address of the filter
* @param address the address to compare the filterSocketAddressWith
* @param ipPrefix the IP address with prefix length to compare the filterSocketAddressWith
* @param startPort the start of the port range to check
* @param endPort the end of the port range to check
*/
@VisibleForTesting
public static boolean matchesAddress(@NonNull final InetSocketAddress filterSocketAddress,
@NonNull final InetAddress address,
final int startPort, final int endPort) {
public static boolean matchesAddress(
@NonNull final InetSocketAddress filterSocketAddress,
@NonNull final IpPrefix ipPrefix,
final int startPort,
final int endPort) {
return startPort <= filterSocketAddress.getPort()
&& endPort >= filterSocketAddress.getPort()
&& (address.isAnyLocalAddress()
|| filterSocketAddress.getAddress().equals(address));
&& (ipPrefix.getAddress().isAnyLocalAddress()
|| ipPrefix.contains(filterSocketAddress.getAddress()));
}
}

View file

@ -1392,6 +1392,22 @@ class NetworkAgentTest {
agent.expectCallback<OnRegisterQosCallback>().let {
callbackId = it.callbackId
assertTrue(it.filter.matchesProtocol(proto))
// This test is only validating QosFilter address match APIs can be called.
// Detail functionality checks are executed on QosSocketFilterTest.
// Verify the match of test socket's Local address, currently the test socket
// binds to the loopback address.
assertTrue(it.filter.matchesLocalPrefix(
IpPrefix(InetAddress.getLoopbackAddress(), 128),
0,
65535
))
// Since the test socket doesn't connect to the remote address, we expect
// unmatched result.
assertFalse(it.filter.matchesRemotePrefix(
IpPrefix(InetAddress.getLoopbackAddress(), 128),
0,
65535
))
}
assertFailsWith<QosCallbackRegistrationException>(

View file

@ -52,50 +52,95 @@ public class QosSocketFilterTest {
public void testPortExactMatch() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
assertTrue(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), addressB, 10, 10));
assertTrue(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), new IpPrefix(addressB, 32), 10, 10));
}
@Test
public void testPortLessThanStart() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
assertFalse(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 8), addressB, 10, 10));
assertFalse(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 8), new IpPrefix(addressB, 32), 10, 10));
}
@Test
public void testPortGreaterThanEnd() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
assertFalse(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 18), addressB, 10, 10));
assertFalse(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 18), new IpPrefix(addressB, 32), 10, 10));
}
@Test
public void testPortBetweenStartAndEnd() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
assertTrue(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), addressB, 8, 18));
assertTrue(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), new IpPrefix(addressB, 32), 8, 18));
}
@Test
public void testAddressesDontMatch() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.5");
assertFalse(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), addressB, 10, 10));
assertFalse(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), new IpPrefix(addressB, 32), 10, 10));
}
@Test
public void testAddressMatchWithAnyLocalAddresses() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("0.0.0.0");
assertTrue(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), addressB, 10, 10));
assertFalse(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressB, 10), addressA, 10, 10));
assertTrue(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), new IpPrefix(addressB, 32), 10, 10));
assertFalse(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressB, 10), new IpPrefix(addressA, 32), 10, 10));
}
@Test
public void testAddressMatchWithPrefixLength() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.100");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.132");
final InetAddress addressC = InetAddresses.parseNumericAddress("1.2.3.96");
final InetAddress addressD = InetAddresses.parseNumericAddress("2001:2:3:5::13:D17");
final InetAddress addressE = InetAddresses.parseNumericAddress("2001:2:3:4::13:D17");
final InetAddress addressF = InetAddresses.parseNumericAddress("2001:2:3:5::");
final InetAddress addressG = InetAddresses.parseNumericAddress("135.23.185.35");
final InetAddress addressH = InetAddresses.parseNumericAddress("135.23.186.127");
final InetAddress addressI = InetAddresses.parseNumericAddress("135.23.183.127");
assertTrue(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), new IpPrefix(addressC, 27), 10, 10));
assertFalse(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressB, 10), new IpPrefix(addressC, 27), 10, 10));
assertTrue(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressG, 10), new IpPrefix(addressH, 22), 10, 10));
assertFalse(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressI, 10), new IpPrefix(addressH, 22), 10, 10));
assertTrue(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressD, 10), new IpPrefix(addressF, 64), 10, 10));
assertFalse(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressE, 10), new IpPrefix(addressF, 64), 10, 10));
assertFalse(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), new IpPrefix(addressF, 64), 10, 10));
assertTrue(
QosSocketFilter.matchesAddress(
new InetSocketAddress(addressD, 10), new IpPrefix(addressD, 128), 10, 10));
}
@Test