Merge changes I4a624ea4,I8626932e
* changes:
Fix a logic error in IpServerTest#addRemoveipv6ForwardingRules
Clear IPv6 forwarding rules when losing upstream or stopping.
diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java
index 3acc766..38f8609 100644
--- a/Tethering/src/android/net/ip/IpServer.java
+++ b/Tethering/src/android/net/ip/IpServer.java
@@ -810,7 +810,7 @@
rule.dstMac.toByteArray());
mIpv6ForwardingRules.put(rule.address, rule);
} catch (RemoteException | ServiceSpecificException e) {
- Log.e(TAG, "Could not add IPv6 downstream rule: " + e);
+ mLog.e("Could not add IPv6 downstream rule: ", e);
}
}
@@ -821,10 +821,17 @@
mIpv6ForwardingRules.remove(rule.address);
}
} catch (RemoteException | ServiceSpecificException e) {
- Log.e(TAG, "Could not remove IPv6 downstream rule: " + e);
+ mLog.e("Could not remove IPv6 downstream rule: ", e);
}
}
+ private void clearIpv6ForwardingRules() {
+ for (Ipv6ForwardingRule rule : mIpv6ForwardingRules.values()) {
+ removeIpv6ForwardingRule(rule, false /*removeFromMap*/);
+ }
+ mIpv6ForwardingRules.clear();
+ }
+
// Convenience method to replace a rule with the same rule on a new upstream interface.
// Allows replacing the rules in one iteration pass without ConcurrentModificationExceptions.
// Relies on the fact that rules are in a map indexed by IP address.
@@ -837,6 +844,12 @@
// changes or if a neighbor event is received.
private void updateIpv6ForwardingRules(int prevUpstreamIfindex, int upstreamIfindex,
NeighborEvent e) {
+ // If we no longer have an upstream, clear forwarding rules and do nothing else.
+ if (upstreamIfindex == 0) {
+ clearIpv6ForwardingRules();
+ return;
+ }
+
// If the upstream interface has changed, remove all rules and re-add them with the new
// upstream interface.
if (prevUpstreamIfindex != upstreamIfindex) {
@@ -846,13 +859,14 @@
}
// If we're here to process a NeighborEvent, do so now.
+ // mInterfaceParams must be non-null or the event would not have arrived.
if (e == null) return;
if (!(e.ip instanceof Inet6Address) || e.ip.isMulticastAddress()
|| e.ip.isLoopbackAddress() || e.ip.isLinkLocalAddress()) {
return;
}
- Ipv6ForwardingRule rule = new Ipv6ForwardingRule(mLastIPv6UpstreamIfindex,
+ Ipv6ForwardingRule rule = new Ipv6ForwardingRule(upstreamIfindex,
mInterfaceParams.index, (Inet6Address) e.ip, mInterfaceParams.macAddr,
e.macAddr);
if (e.isValid()) {
@@ -1095,6 +1109,7 @@
for (String ifname : mUpstreamIfaceSet.ifnames) cleanupUpstreamInterface(ifname);
mUpstreamIfaceSet = null;
+ clearIpv6ForwardingRules();
}
private void cleanupUpstreamInterface(String upstreamIface) {
diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 39742f5..948266d 100644
--- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -43,6 +43,7 @@
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
@@ -546,9 +547,9 @@
reset(mNetd);
// Link-local and multicast neighbors are ignored.
- recvNewNeigh(notMyIfindex, neighLL, NUD_REACHABLE, macA);
+ recvNewNeigh(myIfindex, neighLL, NUD_REACHABLE, macA);
verifyNoMoreInteractions(mNetd);
- recvNewNeigh(notMyIfindex, neighMC, NUD_REACHABLE, macA);
+ recvNewNeigh(myIfindex, neighMC, NUD_REACHABLE, macA);
verifyNoMoreInteractions(mNetd);
// A neighbor that is no longer valid causes the rule to be removed.
@@ -578,6 +579,52 @@
eq(neighB.getAddress()), eq(myMac.toByteArray()), eq(macB.toByteArray()));
inOrder.verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX),
eq(neighB.getAddress()));
+ reset(mNetd);
+
+ // When the upstream is lost, rules are removed.
+ dispatchTetherConnectionChanged(null, null);
+ verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX2),
+ eq(neighA.getAddress()));
+ verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX2),
+ eq(neighB.getAddress()));
+ reset(mNetd);
+
+ // If the upstream is IPv4-only, no rules are added.
+ dispatchTetherConnectionChanged(UPSTREAM_IFACE);
+ reset(mNetd);
+ recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
+ verifyNoMoreInteractions(mNetd);
+
+ // Rules can be added again once upstream IPv6 connectivity is available.
+ lp.setInterfaceName(UPSTREAM_IFACE);
+ dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp);
+ recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
+ verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX),
+ eq(neighB.getAddress()), eq(myMac.toByteArray()), eq(macB.toByteArray()));
+ verify(mNetd, never()).tetherRuleAddDownstreamIpv6(anyInt(), anyInt(),
+ eq(neighA.getAddress()), any(), any());
+
+ // If upstream IPv6 connectivity is lost, rules are removed.
+ reset(mNetd);
+ dispatchTetherConnectionChanged(UPSTREAM_IFACE, null);
+ verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX), eq(neighB.getAddress()));
+
+ // When the interface goes down, rules are removed.
+ lp.setInterfaceName(UPSTREAM_IFACE);
+ dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp);
+ recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
+ recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
+ verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX),
+ eq(neighA.getAddress()), eq(myMac.toByteArray()), eq(macA.toByteArray()));
+ verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX),
+ eq(neighB.getAddress()), eq(myMac.toByteArray()), eq(macB.toByteArray()));
+ reset(mNetd);
+
+ mIpServer.stop();
+ mLooper.dispatchAll();
+ verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX), eq(neighA.getAddress()));
+ verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX), eq(neighB.getAddress()));
+ reset(mNetd);
}
private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception {