Clear IPv4 offload rules when tethering stopped

The condition for deleting IPv4 forwarding rules.
1. When the tethering client has gone, deletes the client and its
   rules.
2. When the upstream has gone, deletes all rules.
3. When the upstream has changed, deletes all rules.

Test: atest TetheringCoverageTests and check IPv4 offload rules
via dumpsys tethering in the following test cases.

Bug: 190783768

Test cases:
a. Loss upstream interface while tethering
  1. Enable WIFI tethering
  2. Disable upstream interface
  3. Check the rules are removed.
b. Loss downstream interfaces while tethering
  1. Enable WIFI tethering
  2. Enable BT tethering
  3. Disable BT tethering
  4. Check the BT tether rules are removed.
  5. Disable WIFI tethering
  6. Check the WIFI tether rules are removed.
c. Switch upstream interface while tethering
  1. Enable WIFI tethering
  2. Enable BT tethering
  3. Switch upstream interface from cellular to wifi.
  4. Check all rules are removed.
d. Enable NAT failure (manual)

Log:
The rule deletion in each case.
- IpServer#stopIPv4: case b and case d.
- BpfCoordinator#updateUpstreamNetworkState: case a and case c.

Test case a
06-23 09:58:59.245  [...] Tethering: [BpfCoordinator]
    updateUpstreamNetworkState tetherOffloadRule4Clear wlan2

Test case b
06-07 22:17:51.886  [..] Tethering: [bt-pan] cleanupUpstream bt-pan
06-07 22:17:51.888  [..] Tethering: [bt-pan] stopIPv4 bt-pan
06-07 22:18:23.769  [..] Tethering: [wlan2] cleanupUpstream wlan2
06-07 22:18:23.772  [..] Tethering: [wlan2] stopIPv4 wlan2

Test case c
06-08 11:11:48.277  [..] Tethering: [BpfCoordinator]
    updateUpstreamNetworkState tetherOffloadRule4Clear bt-pan
06-08 11:11:48.396  [..] Tethering: [BpfCoordinator]
    updateUpstreamNetworkState tetherOffloadRule4Clear wlan2
06-08 11:11:48.579  [..] Tethering: [wlan2] cleanupUpstreamInterface
    wlan2
06-08 11:11:48.808  [..] Tethering: [bt-pan] cleanupUpstreamInterface
    bt-pan

Enabling NAT failure
06-08 13:04:18.117  [..] Tethering: [wlan2] Exception enabling NAT [..]
06-08 13:04:18.234  [..] Tethering: [wlan2] cleanupUpstream wlan2
06-08 13:04:18.246  [..] Tethering: [wlan2] stopIPv4 wlan2

Change-Id: Id505a3deb277bbe0f44403234d8ca8bbf01eec80
This commit is contained in:
Hungming Chen 2021-02-08 17:15:35 +08:00
commit a6e7869646
3 changed files with 281 additions and 64 deletions

View file

@ -33,6 +33,8 @@ import com.android.networkstack.tethering.Tether4Key;
import com.android.networkstack.tethering.Tether4Value;
import com.android.networkstack.tethering.TetherStatsValue;
import java.util.function.BiConsumer;
/**
* Bpf coordinator class for API shims.
*/
@ -160,6 +162,12 @@ public class BpfCoordinatorShimImpl
return true;
}
@Override
public void tetherOffloadRuleForEach(boolean downstream,
@NonNull BiConsumer<Tether4Key, Tether4Value> action) {
/* no op */
}
@Override
public boolean attachProgram(String iface, boolean downstream) {
/* no op */

View file

@ -47,6 +47,7 @@ import com.android.networkstack.tethering.TetherUpstream6Key;
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.function.BiConsumer;
/**
* Bpf coordinator class for API shims.
@ -380,10 +381,7 @@ public class BpfCoordinatorShimImpl
try {
if (downstream) {
if (!mBpfDownstream4Map.deleteEntry(key)) {
mLog.e("Could not delete entry (key: " + key + ")");
return false;
}
if (!mBpfDownstream4Map.deleteEntry(key)) return false; // Rule did not exist
// Decrease the rule count while a deleting rule is not using a given upstream
// interface anymore.
@ -401,18 +399,31 @@ public class BpfCoordinatorShimImpl
mRule4CountOnUpstream.put(upstreamIfindex, count);
}
} else {
mBpfUpstream4Map.deleteEntry(key);
if (!mBpfUpstream4Map.deleteEntry(key)) return false; // Rule did not exist
}
} catch (ErrnoException e) {
// Silent if the rule did not exist.
if (e.errno != OsConstants.ENOENT) {
mLog.e("Could not delete entry: ", e);
return false;
}
mLog.e("Could not delete entry (key: " + key + ")", e);
return false;
}
return true;
}
@Override
public void tetherOffloadRuleForEach(boolean downstream,
@NonNull BiConsumer<Tether4Key, Tether4Value> action) {
if (!isInitialized()) return;
try {
if (downstream) {
mBpfDownstream4Map.forEach(action);
} else {
mBpfUpstream4Map.forEach(action);
}
} catch (ErrnoException e) {
mLog.e("Could not iterate map: ", e);
}
}
@Override
public boolean attachProgram(String iface, boolean downstream) {
if (!isInitialized()) return false;

View file

@ -28,6 +28,8 @@ import com.android.networkstack.tethering.Tether4Key;
import com.android.networkstack.tethering.Tether4Value;
import com.android.networkstack.tethering.TetherStatsValue;
import java.util.function.BiConsumer;
/**
* Bpf coordinator class for API shims.
*/
@ -145,9 +147,24 @@ public abstract class BpfCoordinatorShim {
/**
* Deletes a tethering IPv4 offload rule from the appropriate BPF map.
*
* @param downstream true if downstream, false if upstream.
* @param key the key to delete.
* @return true iff the map was modified, false if the key did not exist or there was an error.
*/
public abstract boolean tetherOffloadRuleRemove(boolean downstream, @NonNull Tether4Key key);
/**
* Iterate through the map and handle each key -> value retrieved base on the given BiConsumer.
*
* @param downstream true if downstream, false if upstream.
* @param action represents the action for each key -> value. The entry deletion is not
* allowed and use #tetherOffloadRuleRemove instead.
*/
@Nullable
public abstract void tetherOffloadRuleForEach(boolean downstream,
@NonNull BiConsumer<Tether4Key, Tether4Value> action);
/**
* Whether there is currently any IPv4 rule on the specified upstream.
*/