Deprecate IPv6 prefixes no longer in use.
Bug: 30298058 Change-Id: I0fa9ece9b2fb07214971a91b77f5b07972d83bb6
This commit is contained in:
@@ -176,9 +176,21 @@ class IPv6TetheringInterfaceServices {
|
|||||||
|
|
||||||
private void updateRaParams(RaParams params) {
|
private void updateRaParams(RaParams params) {
|
||||||
if (mRaDaemon != null) {
|
if (mRaDaemon != null) {
|
||||||
|
HashSet<IpPrefix> deprecated = null;
|
||||||
|
|
||||||
|
if (mLastRaParams != null) {
|
||||||
|
deprecated = new HashSet<>();
|
||||||
|
|
||||||
|
for (IpPrefix ipp : mLastRaParams.prefixes) {
|
||||||
|
if (params == null || !params.prefixes.contains(ipp)) {
|
||||||
|
deprecated.add(ipp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Currently, we send spurious RAs (5) whenever there's any update.
|
// Currently, we send spurious RAs (5) whenever there's any update.
|
||||||
// TODO: Compare params with mLastParams to avoid spurious updates.
|
// TODO: Compare params with mLastParams to avoid spurious updates.
|
||||||
mRaDaemon.buildNewRa(params);
|
mRaDaemon.buildNewRa(params, deprecated);
|
||||||
}
|
}
|
||||||
|
|
||||||
mLastRaParams = params;
|
mLastRaParams = params;
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ import java.nio.BufferOverflowException;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
@@ -109,6 +111,11 @@ public class RouterAdvertisementDaemon {
|
|||||||
private final byte[] mRA = new byte[IPV6_MIN_MTU];
|
private final byte[] mRA = new byte[IPV6_MIN_MTU];
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private int mRaLength;
|
private int mRaLength;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private final HashMap<IpPrefix, Integer> mDeprecatedPrefixes;
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private RaParams mRaParams;
|
||||||
|
|
||||||
private volatile FileDescriptor mSocket;
|
private volatile FileDescriptor mSocket;
|
||||||
private volatile MulticastTransmitter mMulticastTransmitter;
|
private volatile MulticastTransmitter mMulticastTransmitter;
|
||||||
@@ -141,45 +148,29 @@ public class RouterAdvertisementDaemon {
|
|||||||
mIfIndex = ifindex;
|
mIfIndex = ifindex;
|
||||||
mHwAddr = hwaddr;
|
mHwAddr = hwaddr;
|
||||||
mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mIfIndex), 0);
|
mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mIfIndex), 0);
|
||||||
|
mDeprecatedPrefixes = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void buildNewRa(RaParams params) {
|
public void buildNewRa(RaParams params, HashSet<IpPrefix> newlyDeprecated) {
|
||||||
|
if (newlyDeprecated != null) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
for (IpPrefix ipp : newlyDeprecated) {
|
||||||
|
mDeprecatedPrefixes.put(ipp, MAX_URGENT_RTR_ADVERTISEMENTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Send MAX_URGENT_RTR_ADVERTISEMENTS zero router lifetime RAs,
|
||||||
|
// iff. we have already sent an RA.
|
||||||
if (params == null || params.prefixes.isEmpty()) {
|
if (params == null || params.prefixes.isEmpty()) {
|
||||||
// No RA to be served at this time.
|
// No RA to be served at this time.
|
||||||
clearRa();
|
clearRa();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.mtu < IPV6_MIN_MTU) {
|
|
||||||
params.mtu = IPV6_MIN_MTU;
|
|
||||||
}
|
|
||||||
|
|
||||||
final ByteBuffer ra = ByteBuffer.wrap(mRA);
|
|
||||||
ra.order(ByteOrder.BIG_ENDIAN);
|
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
try {
|
mRaParams = params;
|
||||||
putHeader(ra, params.hasDefaultRoute);
|
assembleRa();
|
||||||
putSlla(ra, mHwAddr);
|
|
||||||
// https://tools.ietf.org/html/rfc5175#section-4 says:
|
|
||||||
//
|
|
||||||
// "MUST NOT be added to a Router Advertisement message
|
|
||||||
// if no flags in the option are set."
|
|
||||||
//
|
|
||||||
// putExpandedFlagsOption(ra);
|
|
||||||
putMtu(ra, params.mtu);
|
|
||||||
for (IpPrefix ipp : params.prefixes) {
|
|
||||||
putPio(ra, ipp);
|
|
||||||
}
|
|
||||||
if (params.dnses.size() > 0) {
|
|
||||||
putRdnss(ra, params.dnses);
|
|
||||||
}
|
|
||||||
mRaLength = ra.position();
|
|
||||||
} catch (BufferOverflowException e) {
|
|
||||||
Log.e(TAG, "Could not construct new RA: " + e);
|
|
||||||
mRaLength = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
maybeNotifyMulticastTransmitter();
|
maybeNotifyMulticastTransmitter();
|
||||||
@@ -216,6 +207,64 @@ public class RouterAdvertisementDaemon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assembleRa() {
|
||||||
|
final ByteBuffer ra = ByteBuffer.wrap(mRA);
|
||||||
|
ra.order(ByteOrder.BIG_ENDIAN);
|
||||||
|
|
||||||
|
synchronized (mLock) {
|
||||||
|
try {
|
||||||
|
putHeader(ra, mRaParams.hasDefaultRoute);
|
||||||
|
|
||||||
|
putSlla(ra, mHwAddr);
|
||||||
|
|
||||||
|
// https://tools.ietf.org/html/rfc5175#section-4 says:
|
||||||
|
//
|
||||||
|
// "MUST NOT be added to a Router Advertisement message
|
||||||
|
// if no flags in the option are set."
|
||||||
|
//
|
||||||
|
// putExpandedFlagsOption(ra);
|
||||||
|
|
||||||
|
putMtu(ra, mRaParams.mtu);
|
||||||
|
|
||||||
|
for (IpPrefix ipp : mRaParams.prefixes) {
|
||||||
|
putPio(ra, ipp, DEFAULT_LIFETIME, DEFAULT_LIFETIME);
|
||||||
|
mDeprecatedPrefixes.remove(ipp);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (IpPrefix ipp : mDeprecatedPrefixes.keySet()) {
|
||||||
|
putPio(ra, ipp, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mRaParams.dnses.size() > 0) {
|
||||||
|
putRdnss(ra, mRaParams.dnses);
|
||||||
|
}
|
||||||
|
|
||||||
|
mRaLength = ra.position();
|
||||||
|
} catch (BufferOverflowException e) {
|
||||||
|
Log.e(TAG, "Could not construct new RA: " + e);
|
||||||
|
mRaLength = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int decrementDeprecatedPrefixes() {
|
||||||
|
int removed = 0;
|
||||||
|
|
||||||
|
synchronized (mLock) {
|
||||||
|
for (Map.Entry<IpPrefix, Integer> kv : mDeprecatedPrefixes.entrySet()) {
|
||||||
|
if (kv.getValue() == 0) {
|
||||||
|
mDeprecatedPrefixes.remove(kv.getKey());
|
||||||
|
removed++;
|
||||||
|
} else {
|
||||||
|
kv.setValue(kv.getValue() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
private void maybeNotifyMulticastTransmitter() {
|
private void maybeNotifyMulticastTransmitter() {
|
||||||
final MulticastTransmitter m = mMulticastTransmitter;
|
final MulticastTransmitter m = mMulticastTransmitter;
|
||||||
if (m != null) {
|
if (m != null) {
|
||||||
@@ -325,10 +374,11 @@ public class RouterAdvertisementDaemon {
|
|||||||
ra.put(ND_OPTION_MTU)
|
ra.put(ND_OPTION_MTU)
|
||||||
.put(MTU_NUM_8OCTETS)
|
.put(MTU_NUM_8OCTETS)
|
||||||
.putShort(asShort(0))
|
.putShort(asShort(0))
|
||||||
.putInt(mtu);
|
.putInt((mtu < IPV6_MIN_MTU) ? IPV6_MIN_MTU : mtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void putPio(ByteBuffer ra, IpPrefix ipp) {
|
private static void putPio(ByteBuffer ra, IpPrefix ipp,
|
||||||
|
int validTime, int preferredTime) {
|
||||||
/**
|
/**
|
||||||
Prefix Information
|
Prefix Information
|
||||||
|
|
||||||
@@ -359,13 +409,17 @@ public class RouterAdvertisementDaemon {
|
|||||||
final byte ND_OPTION_PIO = 3;
|
final byte ND_OPTION_PIO = 3;
|
||||||
final byte PIO_NUM_8OCTETS = 4;
|
final byte PIO_NUM_8OCTETS = 4;
|
||||||
|
|
||||||
|
if (validTime < 0) validTime = 0;
|
||||||
|
if (preferredTime < 0) preferredTime = 0;
|
||||||
|
if (preferredTime > validTime) preferredTime = validTime;
|
||||||
|
|
||||||
final byte[] addr = ipp.getAddress().getAddress();
|
final byte[] addr = ipp.getAddress().getAddress();
|
||||||
ra.put(ND_OPTION_PIO)
|
ra.put(ND_OPTION_PIO)
|
||||||
.put(PIO_NUM_8OCTETS)
|
.put(PIO_NUM_8OCTETS)
|
||||||
.put(asByte(prefixLength))
|
.put(asByte(prefixLength))
|
||||||
.put(asByte(0xc0)) // L&A set
|
.put(asByte(0xc0)) /* L & A set */
|
||||||
.putInt(DEFAULT_LIFETIME)
|
.putInt(validTime)
|
||||||
.putInt(DEFAULT_LIFETIME)
|
.putInt(preferredTime)
|
||||||
.putInt(0)
|
.putInt(0)
|
||||||
.put(addr);
|
.put(addr);
|
||||||
}
|
}
|
||||||
@@ -547,6 +601,11 @@ public class RouterAdvertisementDaemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maybeSendRA(mAllNodes);
|
maybeSendRA(mAllNodes);
|
||||||
|
if (decrementDeprecatedPrefixes() > 0) {
|
||||||
|
// At least one deprecated PIO has been removed;
|
||||||
|
// reassemble the RA.
|
||||||
|
assembleRa();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,15 +619,17 @@ public class RouterAdvertisementDaemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int getNextMulticastTransmitDelaySec() {
|
private int getNextMulticastTransmitDelaySec() {
|
||||||
|
int countDeprecatedPrefixes = 0;
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mRaLength < MIN_RA_HEADER_SIZE) {
|
if (mRaLength < MIN_RA_HEADER_SIZE) {
|
||||||
// No actual RA to send; just sleep for 1 day.
|
// No actual RA to send; just sleep for 1 day.
|
||||||
return DAY_IN_SECONDS;
|
return DAY_IN_SECONDS;
|
||||||
}
|
}
|
||||||
|
countDeprecatedPrefixes = mDeprecatedPrefixes.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
final int urgentPending = mUrgentAnnouncements.getAndDecrement();
|
final int urgentPending = mUrgentAnnouncements.getAndDecrement();
|
||||||
if (urgentPending > 0) {
|
if (urgentPending > 0 || countDeprecatedPrefixes > 0) {
|
||||||
return MIN_DELAY_BETWEEN_RAS_SEC;
|
return MIN_DELAY_BETWEEN_RAS_SEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user