Merge "BpfHandler: add 25Q2+ netd map create and write test" into main
diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java
index 6229f6d..609d759 100644
--- a/Tethering/src/android/net/ip/IpServer.java
+++ b/Tethering/src/android/net/ip/IpServer.java
@@ -429,9 +429,11 @@
return Collections.unmodifiableList(mDhcpLeases);
}
- /** Enable this IpServer. IpServer state machine will be tethered or localHotspot state. */
- public void enable(final int requestedState, final TetheringRequest request) {
- sendMessage(CMD_TETHER_REQUESTED, requestedState, 0, request);
+ /**
+ * Enable this IpServer. IpServer state machine will be tethered or localHotspot state based on
+ * the connectivity scope of the TetheringRequest. */
+ public void enable(@NonNull final TetheringRequest request) {
+ sendMessage(CMD_TETHER_REQUESTED, 0, 0, request);
}
/** Stop this IpServer. After this is called this IpServer should not be used any more. */
@@ -1026,11 +1028,11 @@
mLinkProperties.setInterfaceName(mIfaceName);
}
- private void maybeConfigureStaticIp(final TetheringRequest request) {
+ private void maybeConfigureStaticIp(@NonNull final TetheringRequest request) {
// Ignore static address configuration if they are invalid or null. In theory, static
// addresses should not be invalid here because TetheringManager do not allow caller to
// specify invalid static address configuration.
- if (request == null || request.getLocalIpv4Address() == null
+ if (request.getLocalIpv4Address() == null
|| request.getClientStaticIpv4Address() == null || !checkStaticAddressConfiguration(
request.getLocalIpv4Address(), request.getClientStaticIpv4Address())) {
return;
@@ -1053,13 +1055,13 @@
case CMD_TETHER_REQUESTED:
mLastError = TETHER_ERROR_NO_ERROR;
mTetheringRequest = (TetheringRequest) message.obj;
- switch (message.arg1) {
- case STATE_LOCAL_ONLY:
- maybeConfigureStaticIp((TetheringRequest) message.obj);
+ switch (mTetheringRequest.getConnectivityScope()) {
+ case CONNECTIVITY_SCOPE_LOCAL:
+ maybeConfigureStaticIp(mTetheringRequest);
transitionTo(mLocalHotspotState);
break;
- case STATE_TETHERED:
- maybeConfigureStaticIp((TetheringRequest) message.obj);
+ case CONNECTIVITY_SCOPE_GLOBAL:
+ maybeConfigureStaticIp(mTetheringRequest);
transitionTo(mTetheredState);
break;
default:
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 1c8ea3a..21943b0 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -28,6 +28,7 @@
import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
+import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL;
import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL;
import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER;
@@ -73,6 +74,7 @@
import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_P2P;
import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_P2P_SUCCESS;
import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_SUCCESS;
+import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_TETHER_WITH_PLACEHOLDER_REQUEST;
import static com.android.networkstack.tethering.util.TetheringMessageBase.BASE_MAIN_SM;
import android.app.usage.NetworkStatsManager;
@@ -944,9 +946,9 @@
public void onAvailable(String iface) {
if (this != mBluetoothCallback) return;
- final TetheringRequest request = getPendingTetheringRequest(TETHERING_BLUETOOTH);
- enableIpServing(request, TETHERING_BLUETOOTH, iface,
- getRequestedState(TETHERING_BLUETOOTH));
+ final TetheringRequest request =
+ getOrCreatePendingTetheringRequest(TETHERING_BLUETOOTH);
+ enableIpServing(request, iface);
mConfiguredBluetoothIface = iface;
}
@@ -1002,9 +1004,8 @@
return;
}
- final TetheringRequest request = getPendingTetheringRequest(TETHERING_ETHERNET);
- enableIpServing(request, TETHERING_ETHERNET, iface,
- getRequestedState(TETHERING_ETHERNET));
+ final TetheringRequest request = getOrCreatePendingTetheringRequest(TETHERING_ETHERNET);
+ enableIpServing(request, iface);
mConfiguredEthernetIface = iface;
}
@@ -1025,12 +1026,8 @@
} else {
mConfiguredVirtualIface = iface;
}
- final TetheringRequest request = getPendingTetheringRequest(TETHERING_VIRTUAL);
- enableIpServing(
- request,
- TETHERING_VIRTUAL,
- mConfiguredVirtualIface,
- getRequestedState(TETHERING_VIRTUAL));
+ final TetheringRequest request = getOrCreatePendingTetheringRequest(TETHERING_VIRTUAL);
+ enableIpServing(request, mConfiguredVirtualIface);
} else if (mConfiguredVirtualIface != null) {
ensureIpServerStopped(mConfiguredVirtualIface);
mConfiguredVirtualIface = null;
@@ -1040,12 +1037,12 @@
/**
* Create a legacy tethering request for calls to the legacy tether() API, which doesn't take an
- * explicit request.
+ * explicit request. These are always CONNECTIVITY_SCOPE_GLOBAL, per historical behavior.
*/
- private TetheringRequest createLegacyTetheringRequest(int type, int connectivityScope) {
+ private TetheringRequest createLegacyGlobalScopeTetheringRequest(int type) {
final TetheringRequest request = new TetheringRequest.Builder(type).build();
request.getParcel().requestType = TetheringRequest.REQUEST_TYPE_LEGACY;
- request.getParcel().connectivityScope = connectivityScope;
+ request.getParcel().connectivityScope = CONNECTIVITY_SCOPE_GLOBAL;
return request;
}
@@ -1067,7 +1064,8 @@
* Note: There are edge cases where the pending request is absent and we must temporarily
* synthesize a placeholder request, such as if stopTethering was called before link layer
* went up, or if the link layer goes up without us poking it (e.g. adb shell cmd wifi
- * start-softap).
+ * start-softap). These placeholder requests only specify the tethering type and the
+ * default connectivity scope.
*/
@NonNull
private TetheringRequest getOrCreatePendingTetheringRequest(int type) {
@@ -1098,7 +1096,8 @@
} catch (RemoteException e) { }
}
- int result = tetherInternal(null, iface, IpServer.STATE_TETHERED);
+ final TetheringRequest request = createLegacyGlobalScopeTetheringRequest(type);
+ int result = tetherInternal(request, iface);
switch (type) {
case TETHERING_WIFI:
TerribleErrorLog.logTerribleError(TetheringStatsLog::write,
@@ -1150,11 +1149,7 @@
mHandler.post(() -> handleLegacyTether(iface, listener));
}
- // TODO: is it possible to make the request @NonNull here?
- // Because the IpServer doesn't actually look at (almost anything in) the request, we can just
- // make callers synthesize a reasonable-looking request and make this @NonNull.
- private int tetherInternal(@Nullable TetheringRequest request, String iface,
- int requestedState) {
+ private int tetherInternal(@NonNull TetheringRequest request, String iface) {
if (DBG) Log.d(TAG, "Tethering " + iface);
TetherState tetherState = mTetherStates.get(iface);
if (tetherState == null) {
@@ -1171,16 +1166,14 @@
// processed, this will be a no-op and it will not return an error.
//
// This code cannot race with untether() because they both run on the handler thread.
- //
- // TODO: once the request is @NonNull, it will be correct to fetch the type from it, because
- // the type used to fetch (or synthesize) the request is the same as the type passed in at
- // IpServer creation time.
- // BUG: the connectivity scope in the request is ignored. This matches current behaviour.
- // TODO: see if the connectivity scope can be made (or is already) correct, and fetch the
- // requested state from there.
- final int type = tetherState.ipServer.interfaceType();
- mPendingTetheringRequests.remove(type);
- tetherState.ipServer.enable(requestedState, request);
+ mPendingTetheringRequests.remove(request.getTetheringType());
+ tetherState.ipServer.enable(request);
+ if (request.getRequestType() == REQUEST_TYPE_PLACEHOLDER) {
+ TerribleErrorLog.logTerribleError(TetheringStatsLog::write,
+ "Started tethering with placeholder request: " + request,
+ CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED,
+ CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_TETHER_WITH_PLACEHOLDER_REQUEST);
+ }
return TETHER_ERROR_NO_ERROR;
}
@@ -1239,23 +1232,6 @@
return mEntitlementMgr.isTetherProvisioningRequired(cfg);
}
- // TODO: make this take a TetheringRequest instead.
- private int getRequestedState(int type) {
- final TetheringRequest request = mPendingTetheringRequests.get(type);
-
- // The request could have been deleted before we had a chance to complete it.
- // If so, assume that the scope is the default scope for this tethering type.
- // This likely doesn't matter - if the request has been deleted, then tethering is
- // likely going to be stopped soon anyway.
- final int connectivityScope = (request != null)
- ? request.getConnectivityScope()
- : TetheringRequest.getDefaultConnectivityScope(type);
-
- return connectivityScope == CONNECTIVITY_SCOPE_LOCAL
- ? IpServer.STATE_LOCAL_ONLY
- : IpServer.STATE_TETHERED;
- }
-
private int getServedUsbType(boolean forNcmFunction) {
// TETHERING_NCM is only used if the device does not use NCM for regular USB tethering.
if (forNcmFunction && !mConfig.isUsingNcm()) return TETHERING_NCM;
@@ -1621,17 +1597,13 @@
return mPendingTetheringRequests.get(type, null);
}
- // TODO: make the request @NonNull and move the tetheringType and ipServingMode into it.
- private void enableIpServing(@Nullable TetheringRequest request, int tetheringType,
- String ifname, int ipServingMode) {
- enableIpServing(request, tetheringType, ifname, ipServingMode, false /* isNcm */);
+ private void enableIpServing(@NonNull TetheringRequest request, String ifname) {
+ enableIpServing(request, ifname, false /* isNcm */);
}
- // TODO: make the request @NonNull and move the tetheringType and ipServingMode into it.
- private void enableIpServing(@Nullable TetheringRequest request, int tetheringType,
- String ifname, int ipServingMode, boolean isNcm) {
- ensureIpServerStartedForType(ifname, tetheringType, isNcm);
- if (tetherInternal(request, ifname, ipServingMode) != TETHER_ERROR_NO_ERROR) {
+ private void enableIpServing(@NonNull TetheringRequest request, String ifname, boolean isNcm) {
+ ensureIpServerStartedForType(ifname, request.getTetheringType(), isNcm);
+ if (tetherInternal(request, ifname) != TETHER_ERROR_NO_ERROR) {
Log.e(TAG, "unable start tethering on iface " + ifname);
}
}
@@ -1683,9 +1655,10 @@
mLog.e(ifname + " is not a tetherable iface, ignoring");
return;
}
- // No need to look for active requests. There can never be explicit requests for
+ // No need to call getOrCreatePendingRequest. There can never be explicit requests for
// TETHERING_WIFI_P2P because enableTetheringInternal ignores that type.
- enableIpServing(null, type, ifname, IpServer.STATE_LOCAL_ONLY);
+ final TetheringRequest request = createImplicitLocalOnlyTetheringRequest(type);
+ enableIpServing(request, ifname);
}
private void disableWifiP2pIpServingIfNeeded(String ifname) {
@@ -1707,16 +1680,20 @@
// Map wifiIpMode values to IpServer.Callback serving states.
TetheringRequest request;
- final int ipServingMode;
final int type;
switch (wifiIpMode) {
case IFACE_IP_MODE_TETHERED:
- ipServingMode = IpServer.STATE_TETHERED;
type = maybeInferWifiTetheringType(ifname);
- request = getPendingTetheringRequest(type);
+ request = getOrCreatePendingTetheringRequest(type);
+ // Wifi requests will always have CONNECTIVITY_SCOPE_GLOBAL, because
+ // TetheringRequest.Builder will not allow callers to set CONNECTIVITY_SCOPE_LOCAL
+ // for TETHERING_WIFI. However, if maybeInferWifiTetheringType returns a non-Wifi
+ // type (which could happen on a pre-T implementation of Wi-Fi if the regexps are
+ // misconfigured), then force the connectivity scope to global in order to match the
+ // historical behavior.
+ request.getParcel().connectivityScope = CONNECTIVITY_SCOPE_GLOBAL;
break;
case IFACE_IP_MODE_LOCAL_ONLY:
- ipServingMode = IpServer.STATE_LOCAL_ONLY;
type = maybeInferWifiTetheringType(ifname);
// BUG: this request is incorrect - instead of LOHS, it will reflect whatever
// request (if any) is being processed for TETHERING_WIFI. However, this is the
@@ -1724,6 +1701,21 @@
// such request b) tetherinternal doesn't look at the connectivity scope of the
// request, it takes the scope from requestedState.
request = getPendingTetheringRequest(type);
+ if (request == null) {
+ request = createImplicitLocalOnlyTetheringRequest(TETHERING_WIFI);
+ } else {
+ // If we've taken this request from the pending requests, then force the
+ // connectivity scope to local so we start IpServer in local-only mode (this
+ // matches historical behavior). This should be OK since the connectivity scope
+ // is only used to start IpServer in the correct mode.
+ // TODO: This will break fuzzy-matching logic for start/stop tethering in the
+ // future. Figure out how to reconcile that with this forced scope.
+ // Possibly ignore the connectivity scope for wifi if both requests are
+ // explicit, since explicit Wifi requests may only have
+ // CONNECTIVITY_SCOPE_GLOBAL. Or possibly, don't add any edge case and
+ // treat it as a different request entirely.
+ request.getParcel().connectivityScope = CONNECTIVITY_SCOPE_LOCAL;
+ }
break;
default:
mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode);
@@ -1738,7 +1730,7 @@
}
if (!TextUtils.isEmpty(ifname)) {
- enableIpServing(request, type, ifname, ipServingMode);
+ enableIpServing(request, ifname);
} else {
mLog.e("Cannot enable IP serving on missing interface name");
}
@@ -1759,7 +1751,6 @@
// for both TETHERING_USB and TETHERING_NCM, so the local-only NCM interface will be
// stopped immediately.
final int tetheringType = getServedUsbType(forNcmFunction);
- final int requestedState = getRequestedState(tetheringType);
String[] ifaces = null;
try {
ifaces = mNetd.interfaceGetList();
@@ -1768,11 +1759,11 @@
return;
}
- final TetheringRequest request = getPendingTetheringRequest(tetheringType);
+ final TetheringRequest request = getOrCreatePendingTetheringRequest(tetheringType);
if (ifaces != null) {
for (String iface : ifaces) {
if (ifaceNameToType(iface) == tetheringType) {
- enableIpServing(request, tetheringType, iface, requestedState, forNcmFunction);
+ enableIpServing(request, iface, forNcmFunction);
return;
}
}
diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 680e81d..84b301f 100644
--- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -48,7 +48,6 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.clearInvocations;
@@ -74,6 +73,7 @@
import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.RouteInfo;
+import android.net.TetheringManager.TetheringRequest;
import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.IDhcpEventCallbacks;
@@ -240,7 +240,8 @@
Set<LinkAddress> upstreamAddresses, boolean usingLegacyDhcp, boolean usingBpfOffload)
throws Exception {
initStateMachine(interfaceType, usingLegacyDhcp, usingBpfOffload);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
+ dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
+ createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
verify(mBpfCoordinator).addIpServer(mIpServer);
if (upstreamIface != null) {
InterfaceParams interfaceParams = mDependencies.getInterfaceParams(upstreamIface);
@@ -345,7 +346,8 @@
public void canBeTetheredAsBluetooth() throws Exception {
initStateMachine(TETHERING_BLUETOOTH);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
+ dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
+ createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager);
if (isAtLeastT()) {
inOrder.verify(mRoutingCoordinatorManager)
@@ -400,7 +402,8 @@
public void canBeTetheredAsUsb() throws Exception {
initStateMachine(TETHERING_USB);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
+ dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
+ createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager);
inOrder.verify(mRoutingCoordinatorManager).requestStickyDownstreamAddress(anyInt(),
eq(CONNECTIVITY_SCOPE_GLOBAL), any());
@@ -423,7 +426,8 @@
public void canBeTetheredAsWifiP2p_NotUsingDedicatedIp() throws Exception {
initStateMachine(TETHERING_WIFI_P2P);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
+ dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
+ createMockTetheringRequest(CONNECTIVITY_SCOPE_LOCAL));
InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager);
inOrder.verify(mRoutingCoordinatorManager).requestStickyDownstreamAddress(anyInt(),
eq(CONNECTIVITY_SCOPE_LOCAL), any());
@@ -447,7 +451,8 @@
initStateMachine(TETHERING_WIFI_P2P, false /* usingLegacyDhcp */, DEFAULT_USING_BPF_OFFLOAD,
true /* shouldEnableWifiP2pDedicatedIp */);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
+ dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
+ createMockTetheringRequest(CONNECTIVITY_SCOPE_LOCAL));
InOrder inOrder = inOrder(mCallback, mNetd, mRoutingCoordinatorManager);
// When using WiFi P2p dedicated IP, the IpServer just picks the IP address without
// requesting for it at RoutingCoordinatorManager.
@@ -627,7 +632,8 @@
initStateMachine(TETHERING_USB);
doThrow(RemoteException.class).when(mNetd).tetherInterfaceAdd(IFACE_NAME);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
+ dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
+ createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
InOrder usbTeardownOrder = inOrder(mNetd, mCallback);
usbTeardownOrder.verify(mNetd).interfaceSetCfg(
argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
@@ -713,7 +719,8 @@
@Test
public void startsDhcpServerOnNcm() throws Exception {
initStateMachine(TETHERING_NCM);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
+ dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
+ createMockTetheringRequest(CONNECTIVITY_SCOPE_LOCAL));
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
assertDhcpStarted(new IpPrefix("192.168.42.0/24"));
@@ -722,7 +729,8 @@
@Test
public void testOnNewPrefixRequest() throws Exception {
initStateMachine(TETHERING_NCM);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
+ dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
+ createMockTetheringRequest(CONNECTIVITY_SCOPE_LOCAL));
final IDhcpEventCallbacks eventCallbacks;
final ArgumentCaptor<IDhcpEventCallbacks> dhcpEventCbsCaptor =
@@ -911,7 +919,8 @@
doNothing().when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(),
cbCaptor.capture());
initStateMachine(TETHERING_WIFI);
- dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
+ dispatchCommand(IpServer.CMD_TETHER_REQUESTED, 0, 0,
+ createMockTetheringRequest(CONNECTIVITY_SCOPE_GLOBAL));
verify(mDhcpServer, never()).startWithCallbacks(any(), any());
// No stop dhcp server because dhcp server is not created yet.
@@ -957,14 +966,22 @@
assertDhcpServingParams(mDhcpParamsCaptor.getValue(), expectedPrefix);
}
+ private TetheringRequest createMockTetheringRequest(int connectivityScope) {
+ TetheringRequest request = mock(TetheringRequest.class);
+ when(request.getConnectivityScope()).thenReturn(connectivityScope);
+ return request;
+ }
+
/**
* Send a command to the state machine under test, and run the event loop to idle.
*
* @param command One of the IpServer.CMD_* constants.
- * @param arg1 An additional argument to pass.
+ * @param arg1 An additional argument to pass.
+ * @param arg2 An additional argument to pass.
+ * @param obj An additional object to pass.
*/
- private void dispatchCommand(int command, int arg1) {
- mIpServer.sendMessage(command, arg1);
+ private void dispatchCommand(int command, int arg1, int arg2, Object obj) {
+ mIpServer.sendMessage(command, arg1, arg2, obj);
mLooper.dispatchAll();
}
diff --git a/bpf/headers/include/bpf_helpers.h b/bpf/headers/include/bpf_helpers.h
index 67de633..6a0e5a8 100644
--- a/bpf/headers/include/bpf_helpers.h
+++ b/bpf/headers/include/bpf_helpers.h
@@ -419,6 +419,22 @@
DEFINE_BPF_MAP_UGM(the_map, TYPE, KeyType, ValueType, num_entries, \
DEFAULT_BPF_MAP_UID, gid, 0660)
+// idea from Linux include/linux/compiler_types.h (eBPF is always a 64-bit arch)
+#define NATIVE_WORD(t) ((sizeof(t) == 1) || (sizeof(t) == 2) || (sizeof(t) == 4) || (sizeof(t) == 8))
+
+// simplified from Linux include/asm-generic/rwonce.h
+#define READ_ONCE(x) \
+ ({ \
+ _Static_assert(NATIVE_WORD(x), "READ_ONCE requires a native word size"); \
+ (*(const volatile typeof(x) *)&(x)) \
+ })
+
+#define WRITE_ONCE(x, value) \
+ do { \
+ _Static_assert(NATIVE_WORD(x), "WRITE_ONCE requires a native word size"); \
+ *(volatile typeof(x) *)&(x) = (value); \
+ } while (0)
+
// LLVM eBPF builtins: they directly generate BPF_LD_ABS/BPF_LD_IND (skb may be ignored?)
unsigned long long load_byte(void* skb, unsigned long long off) asm("llvm.bpf.load.byte");
unsigned long long load_half(void* skb, unsigned long long off) asm("llvm.bpf.load.half");
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 7f03a02..00c87a3 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -2331,8 +2331,10 @@
// Verify that turning airplane mode off takes effect as expected.
// connectToCell only registers a request, it cannot / does not need to be called twice
- mCtsNetUtils.ensureWifiConnected();
- if (verifyWifi) waitForAvailable(wifiCb);
+ if (verifyWifi) {
+ mCtsNetUtils.ensureWifiConnected();
+ waitForAvailable(wifiCb);
+ }
if (supportTelephony) {
telephonyCb.eventuallyExpect(
CallbackEntry.AVAILABLE, CELL_DATA_AVAILABLE_TIMEOUT_MS);