IPv6RA: Property configuration support added.
Change-Id: Ie2270fdf1449ae401713fc2cf5ae7cdd07f55b69
diff --git a/apps/routeradvertisement/src/main/java/org/onosproject/ra/RouterAdvertisementManager.java b/apps/routeradvertisement/src/main/java/org/onosproject/ra/RouterAdvertisementManager.java
index cfefa84..e3daceb 100644
--- a/apps/routeradvertisement/src/main/java/org/onosproject/ra/RouterAdvertisementManager.java
+++ b/apps/routeradvertisement/src/main/java/org/onosproject/ra/RouterAdvertisementManager.java
@@ -22,6 +22,7 @@
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Modified;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ICMP6;
@@ -81,6 +82,12 @@
private static final int DEFAULT_RA_THREADS_POOL_SIZE = 10;
private static final String PROP_RA_THREADS_DELAY = "raThreadDelay";
private static final int DEFAULT_RA_THREADS_DELAY = 5;
+ private static final String PROP_RA_FLAG_MBIT_STATUS = "raFlagMbitStatus";
+ private static final boolean DEFAULT_RA_FLAG_MBIT_STATUS = false;
+ private static final String PROP_RA_FLAG_OBIT_STATUS = "raFlagObitStatus";
+ private static final boolean DEFAULT_RA_FLAG_OBIT_STATUS = false;
+ private static final String PROP_RA_OPTION_PREFIX_STATUS = "raOptionPrefixStatus";
+ private static final boolean DEFAULT_RA_OPTION_PREFIX_STATUS = true;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@@ -98,13 +105,25 @@
public MastershipService mastershipService;
@Property(name = PROP_RA_THREADS_POOL, intValue = DEFAULT_RA_THREADS_POOL_SIZE,
- label = "Router Advertisement thread pool capacity")
+ label = "Thread pool capacity")
protected int raPoolSize = DEFAULT_RA_THREADS_POOL_SIZE;
@Property(name = PROP_RA_THREADS_DELAY, intValue = DEFAULT_RA_THREADS_DELAY,
- label = "Router Advertisement thread delay in seconds")
+ label = "Thread delay in seconds")
protected int raThreadDelay = DEFAULT_RA_THREADS_DELAY;
+ @Property(name = PROP_RA_FLAG_MBIT_STATUS, boolValue = DEFAULT_RA_FLAG_MBIT_STATUS,
+ label = "Turn M-bit flag on/off")
+ protected boolean raFlagMbitStatus = DEFAULT_RA_FLAG_MBIT_STATUS;
+
+ @Property(name = PROP_RA_FLAG_OBIT_STATUS, boolValue = DEFAULT_RA_FLAG_OBIT_STATUS,
+ label = "Turn O-bit flag on/off")
+ protected boolean raFlagObitStatus = DEFAULT_RA_FLAG_OBIT_STATUS;
+
+ @Property(name = PROP_RA_OPTION_PREFIX_STATUS, boolValue = DEFAULT_RA_OPTION_PREFIX_STATUS,
+ label = "Prefix option support needed or not")
+ protected boolean raOptionPrefixStatus = DEFAULT_RA_OPTION_PREFIX_STATUS;
+
private ScheduledExecutorService executors = null;
@GuardedBy(value = "this")
@@ -134,6 +153,13 @@
}
break;
case INTERFACE_UPDATED:
+ if (mastershipService.getLocalRole(i.connectPoint().deviceId())
+ == MastershipRole.MASTER) {
+ deactivateRouterAdvertisement(i.connectPoint(),
+ i.ipAddressesList());
+ activateRouterAdvertisement(i.connectPoint(),
+ i.ipAddressesList());
+ }
break;
default:
break;
@@ -143,58 +169,37 @@
private final InterfaceListener interfaceListener = new InternalInterfaceListener();
// Enables RA threads on 'connectPoint' with configured IPv6s
- private void activateRouterAdvertisement(ConnectPoint connectPoint, List<InterfaceIpAddress> addresses) {
- synchronized (this) {
+ private synchronized void activateRouterAdvertisement(ConnectPoint connectPoint,
+ List<InterfaceIpAddress> addresses) {
RAWorkerThread worker = new RAWorkerThread(connectPoint, addresses, raThreadDelay);
ScheduledFuture<?> handler = executors.scheduleAtFixedRate(worker, raThreadDelay,
raThreadDelay, TimeUnit.SECONDS);
transmitters.put(connectPoint, handler);
- }
-
}
// Disables already activated RA threads on 'connectPoint'
- private void deactivateRouterAdvertisement(ConnectPoint connectPoint, List<InterfaceIpAddress> addresses) {
- synchronized (this) {
+ private synchronized void deactivateRouterAdvertisement(ConnectPoint connectPoint,
+ List<InterfaceIpAddress> addresses) {
if (connectPoint != null) {
ScheduledFuture<?> handler = transmitters.get(connectPoint);
handler.cancel(false);
transmitters.remove(connectPoint);
}
- }
}
- @Activate
- protected void activate(ComponentContext context) {
- // Basic application registrations.
- appId = coreService.registerApplication(APP_NAME);
- componentConfigService.registerProperties(getClass());
-
- // Loading configured properties.
- if (context != null) {
- Dictionary<?, ?> properties = context.getProperties();
- try {
- String s = get(properties, PROP_RA_THREADS_POOL);
- raPoolSize = isNullOrEmpty(s) ?
- DEFAULT_RA_THREADS_POOL_SIZE : Integer.parseInt(s.trim());
-
- s = get(properties, PROP_RA_THREADS_DELAY);
- raThreadDelay = isNullOrEmpty(s) ?
- DEFAULT_RA_THREADS_DELAY : Integer.parseInt(s.trim());
-
- } catch (NumberFormatException e) {
- log.warn("Component configuration had invalid value, loading default values.", e);
- }
- }
-
- // Interface listener for dynamic RA handling.
- interfaceService.addListener(interfaceListener);
-
+ private synchronized void setupThreadPool() {
// Initialize RA thread pool
executors = Executors.newScheduledThreadPool(raPoolSize,
groupedThreads("RouterAdvertisement", "event-%d", log));
+ }
- // Start Router Advertisement Transmission for all configured interfaces.
+ private synchronized void clearThreadPool() {
+ // Release RA thread pool
+ executors.shutdown();
+ }
+
+ private synchronized void setupTxWorkers() {
+ // Start Router Advertisement transmission for all configured interfaces.
interfaceService.getInterfaces()
.stream()
.filter(i -> mastershipService.getLocalRole(i.connectPoint().deviceId())
@@ -207,12 +212,7 @@
);
}
- @Deactivate
- protected void deactivate() {
- // Unregister resources.
- componentConfigService.unregisterProperties(getClass(), false);
- interfaceService.removeListener(interfaceListener);
-
+ private synchronized void clearTxWorkers() {
// Clear out Router Advertisement Transmission for all configured interfaces.
interfaceService.getInterfaces()
.stream()
@@ -226,6 +226,90 @@
);
}
+ // Setting up pool & workers.
+ private synchronized void setupPoolAndTxWorkers() {
+ setupThreadPool();
+ setupTxWorkers();
+ }
+
+ // Clearing pool & workers.
+ private synchronized void clearPoolAndTxWorkers() {
+ clearTxWorkers();
+ clearThreadPool();
+ }
+
+ @Activate
+ protected void activate(ComponentContext context) {
+ // Basic application registrations.
+ appId = coreService.registerApplication(APP_NAME);
+ componentConfigService.registerProperties(getClass());
+
+ // Interface listener for dynamic RA handling.
+ interfaceService.addListener(interfaceListener);
+
+ // Setup pool and worker threads for existing interfaces
+ setupPoolAndTxWorkers();
+ }
+
+ @Modified
+ protected void modified(ComponentContext context) {
+ int newRaPoolSize, newRaThreadDelay;
+
+ // Loading configured properties.
+ if (context != null) {
+ Dictionary<?, ?> properties = context.getProperties();
+ try {
+ // Handle change in pool size
+ String s = get(properties, PROP_RA_THREADS_POOL);
+ newRaPoolSize = isNullOrEmpty(s) ?
+ DEFAULT_RA_THREADS_POOL_SIZE : Integer.parseInt(s.trim());
+ if (newRaPoolSize != raPoolSize) {
+ raPoolSize = newRaPoolSize;
+ clearPoolAndTxWorkers();
+ setupPoolAndTxWorkers();
+ }
+
+ // Handle change in thread delay
+ s = get(properties, PROP_RA_THREADS_DELAY);
+ newRaThreadDelay = isNullOrEmpty(s) ?
+ DEFAULT_RA_THREADS_DELAY : Integer.parseInt(s.trim());
+ if (newRaThreadDelay != raThreadDelay) {
+ raThreadDelay = newRaThreadDelay;
+ clearTxWorkers();
+ setupTxWorkers();
+ }
+
+ // Handle M-flag changes
+ s = get(properties, PROP_RA_FLAG_MBIT_STATUS);
+ raFlagMbitStatus = isNullOrEmpty(s) ?
+ DEFAULT_RA_FLAG_MBIT_STATUS : Boolean.parseBoolean(s.trim());
+
+ // Handle O-flag changes
+ s = get(properties, PROP_RA_FLAG_OBIT_STATUS);
+ raFlagObitStatus = isNullOrEmpty(s) ?
+ DEFAULT_RA_FLAG_OBIT_STATUS : Boolean.parseBoolean(s.trim());
+
+ // Handle prefix option configuration
+ s = get(properties, PROP_RA_OPTION_PREFIX_STATUS);
+ raOptionPrefixStatus = isNullOrEmpty(s) ?
+ DEFAULT_RA_OPTION_PREFIX_STATUS : Boolean.parseBoolean(s.trim());
+
+ } catch (NumberFormatException e) {
+ log.warn("Component configuration had invalid value, aborting changes loading.", e);
+ }
+ }
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ // Unregister resources.
+ componentConfigService.unregisterProperties(getClass(), false);
+ interfaceService.removeListener(interfaceListener);
+
+ // Clear pool & threads
+ clearPoolAndTxWorkers();
+ }
+
// Worker thread for actually sending ICMPv6 RA packets.
private class RAWorkerThread implements Runnable {
@@ -253,8 +337,8 @@
// Router Advertisement header filling. Please refer RFC-2461.
RouterAdvertisement ra = new RouterAdvertisement();
ra.setCurrentHopLimit(RA_HOP_LIMIT);
- ra.setMFlag((byte) 0x01);
- ra.setOFlag((byte) 0x00);
+ ra.setMFlag((byte) (raFlagMbitStatus ? 0x01 : 0x00));
+ ra.setOFlag((byte) (raFlagObitStatus ? 0x01 : 0x00));
ra.setRouterLifetime(RA_ROUTER_LIFETIME);
ra.setReachableTime(0);
ra.setRetransmitTimer(retransmitPeriod + RA_RETRANSMIT_CALIBRATION_PERIOD);
@@ -280,23 +364,25 @@
Arrays.copyOfRange(option.array(), 0, option.position()));
// Option : Prefix information.
- ipAddresses.stream()
- .filter(i -> i.ipAddress().version().equals(IpAddress.Version.INET6))
- .forEach(i -> {
- option.rewind();
- option.put((byte) i.subnetAddress().prefixLength());
- // Enable "onlink" option only.
- option.put((byte) 0x80);
- option.putInt(RA_OPTION_PREFIX_VALID_LIFETIME);
- option.putInt(RA_OPTION_PREFIX_PREFERRED_LIFETIME);
- // Clear reserved fields
- option.putInt(0x00000000);
- option.put(IpAddress.makeMaskedAddress(i.ipAddress(),
- i.subnetAddress().prefixLength()).toOctets());
- ra.addOption(NeighborDiscoveryOptions.TYPE_PREFIX_INFORMATION,
- Arrays.copyOfRange(option.array(), 0, option.position()));
+ if (raOptionPrefixStatus) {
+ ipAddresses.stream()
+ .filter(i -> i.ipAddress().version().equals(IpAddress.Version.INET6))
+ .forEach(i -> {
+ option.rewind();
+ option.put((byte) i.subnetAddress().prefixLength());
+ // Enable "onlink" option only.
+ option.put((byte) 0x80);
+ option.putInt(RA_OPTION_PREFIX_VALID_LIFETIME);
+ option.putInt(RA_OPTION_PREFIX_PREFERRED_LIFETIME);
+ // Clear reserved fields
+ option.putInt(0x00000000);
+ option.put(IpAddress.makeMaskedAddress(i.ipAddress(),
+ i.subnetAddress().prefixLength()).toOctets());
+ ra.addOption(NeighborDiscoveryOptions.TYPE_PREFIX_INFORMATION,
+ Arrays.copyOfRange(option.array(), 0, option.position()));
- });
+ });
+ }
// ICMPv6 header filling.
ICMP6 icmpv6 = new ICMP6();