Pavlin Radoslavov

Add explicit configuration for enabling IPv6-related flow installation

(IPv6 Neighbor Discovery related flow mods).
The default configuration is false (disabled).

This fixes ONOS-1146

The configurable parameters are:

 tools/package/etc/org.onosproject.provider.host.impl.HostLocationProvider.cfg
  - Enable host removal on port/device down events.
    (NOTE: not IPv6 related, added for completeness)
    hostRemovalEnabled = true
  - Enable using IPv6 Neighbor Discovery by the Host Location Provider.
    ipv6NeighborDiscovery = false

 tools/package/etc/org.onosproject.proxyarp.ProxyArp.cfg
  - Enable IPv6 Neighbor Discovery.
    ipv6NeighborDiscovery = false

NOTE: The above IPv6-related configuration has drawbacks,
partially because of some PacketService-related side effects.
Currently, we don't support enabling ipv6NeighborDiscovery
in one of the configuration files, and disabling it in another.
Enabling ipv6NeighborDiscovery in one configuration file is
practically equivalent to enabling it in both places.

Change-Id: Ief558697d85c8dcffc8941c575d0bf7d1397d90d
......@@ -31,4 +31,11 @@
<description>ONOS simple proxy arp module</description>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
</dependencies>
</project>
......
......@@ -15,9 +15,13 @@
*/
package org.onosproject.proxyarp;
import java.util.Dictionary;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
......@@ -32,8 +36,10 @@ import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.proxyarp.ProxyArpService;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.slf4j.LoggerFactory.getLogger;
/**
......@@ -57,9 +63,15 @@ public class ProxyArp {
private ApplicationId appId;
@Property(name = "ipv6NeighborDiscovery", boolValue = false,
label = "Enable IPv6 Neighbor Discovery; default is false")
private boolean ipv6NeighborDiscovery = false;
@Activate
public void activate() {
public void activate(ComponentContext context) {
appId = coreService.registerApplication("org.onosproject.proxyarp");
readComponentConfiguration(context);
packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 1);
TrafficSelector.Builder selectorBuilder =
......@@ -68,21 +80,23 @@ public class ProxyArp {
packetService.requestPackets(selectorBuilder.build(),
PacketPriority.CONTROL, appId);
// IPv6 Neighbor Solicitation packet.
selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
packetService.requestPackets(selectorBuilder.build(),
PacketPriority.CONTROL, appId);
// IPv6 Neighbor Advertisement packet.
selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
packetService.requestPackets(selectorBuilder.build(),
PacketPriority.CONTROL, appId);
if (ipv6NeighborDiscovery) {
// IPv6 Neighbor Solicitation packet.
selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
packetService.requestPackets(selectorBuilder.build(),
PacketPriority.CONTROL, appId);
// IPv6 Neighbor Advertisement packet.
selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
packetService.requestPackets(selectorBuilder.build(),
PacketPriority.CONTROL, appId);
}
log.info("Started with Application ID {}", appId.id());
}
......@@ -94,6 +108,50 @@ public class ProxyArp {
log.info("Stopped");
}
@Modified
public void modified(ComponentContext context) {
readComponentConfiguration(context);
}
/**
* Extracts properties from the component configuration context.
*
* @param context the component context
*/
private void readComponentConfiguration(ComponentContext context) {
Dictionary<?, ?> properties = context.getProperties();
Boolean flag;
flag = isPropertyEnabled(properties, "ipv6NeighborDiscovery");
if (flag == null) {
log.info("IPv6 Neighbor Discovery is not configured, " +
"using current value of {}", ipv6NeighborDiscovery);
} else {
ipv6NeighborDiscovery = flag;
log.info("Configured. IPv6 Neighbor Discovery is {}",
ipv6NeighborDiscovery ? "enabled" : "disabled");
}
}
/**
* Check property name is defined and set to true.
*
* @param properties properties to be looked up
* @param propertyName the name of the property to look up
* @return value when the propertyName is defined or return null
*/
private static Boolean isPropertyEnabled(Dictionary<?, ?> properties,
String propertyName) {
Boolean value = null;
try {
String s = (String) properties.get(propertyName);
value = isNullOrEmpty(s) ? null : s.trim().equals("true");
} catch (ClassCastException e) {
// No propertyName defined.
value = null;
}
return value;
}
/**
* Packet processor responsible for forwarding packets along their paths.
......
......@@ -15,6 +15,7 @@
*/
package org.onosproject.provider.host.impl;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Dictionary;
......@@ -103,6 +104,10 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
label = "Enable host removal on port/device down events")
private boolean hostRemovalEnabled = true;
@Property(name = "ipv6NeighborDiscovery", boolValue = false,
label = "Enable using IPv6 Neighbor Discovery by the " +
"Host Location Provider; default is false")
private boolean ipv6NeighborDiscovery = false;
/**
* Creates an OpenFlow host provider.
......@@ -115,8 +120,8 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
public void activate(ComponentContext context) {
appId =
coreService.registerApplication("org.onosproject.provider.host");
readComponentConfiguration(context);
modified(context);
providerService = providerRegistry.register(this);
packetService.addProcessor(processor, 1);
deviceService.addListener(deviceListener);
......@@ -127,21 +132,23 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
packetService.requestPackets(selectorBuilder.build(),
PacketPriority.CONTROL, appId);
// IPv6 Neighbor Solicitation packet.
selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
packetService.requestPackets(selectorBuilder.build(),
PacketPriority.CONTROL, appId);
// IPv6 Neighbor Advertisement packet.
selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
packetService.requestPackets(selectorBuilder.build(),
PacketPriority.CONTROL, appId);
if (ipv6NeighborDiscovery) {
// IPv6 Neighbor Solicitation packet.
selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
packetService.requestPackets(selectorBuilder.build(),
PacketPriority.CONTROL, appId);
// IPv6 Neighbor Advertisement packet.
selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
packetService.requestPackets(selectorBuilder.build(),
PacketPriority.CONTROL, appId);
}
log.info("Started with Application ID {}", appId.id());
}
......@@ -157,17 +164,57 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
@Modified
public void modified(ComponentContext context) {
Dictionary properties = context.getProperties();
readComponentConfiguration(context);
}
/**
* Extracts properties from the component configuration context.
*
* @param context the component context
*/
private void readComponentConfiguration(ComponentContext context) {
Dictionary<?, ?> properties = context.getProperties();
Boolean flag;
flag = isPropertyEnabled(properties, "hostRemovalEnabled");
if (flag == null) {
log.info("Host removal on port/device down events is not configured, " +
"using current value of {}", hostRemovalEnabled);
} else {
hostRemovalEnabled = flag;
log.info("Configured. Host removal on port/device down events is {}",
hostRemovalEnabled ? "enabled" : "disabled");
}
flag = isPropertyEnabled(properties, "ipv6NeighborDiscovery");
if (flag == null) {
log.info("Using IPv6 Neighbor Discovery is not configured, " +
"using current value of {}", ipv6NeighborDiscovery);
} else {
ipv6NeighborDiscovery = flag;
log.info("Configured. Using IPv6 Neighbor Discovery is {}",
ipv6NeighborDiscovery ? "enabled" : "disabled");
}
}
/**
* Check property name is defined and set to true.
*
* @param properties properties to be looked up
* @param propertyName the name of the property to look up
* @return value when the propertyName is defined or return null
*/
private static Boolean isPropertyEnabled(Dictionary<?, ?> properties,
String propertyName) {
Boolean value = null;
try {
String flag = (String) properties.get("hostRemovalEnabled");
if (flag != null) {
hostRemovalEnabled = flag.equals("true");
}
String s = (String) properties.get(propertyName);
value = isNullOrEmpty(s) ? null : s.trim().equals("true");
} catch (ClassCastException e) {
hostRemovalEnabled = true;
// No propertyName defined.
value = null;
}
log.info("Host removal is {}",
hostRemovalEnabled ? "enabled" : "disabled");
return value;
}
@Override
......
#
# Sample configuration for Host Location Provider
# This configuration file would be placed at: $(KARAF_ROOT)/etc.
#
# Enable host removal on port/device down events.
#
# hostRemovalEnabled = true
#
# Enable using IPv6 Neighbor Discovery by the Host Location Provider.
#
# ipv6NeighborDiscovery = false
#
# Sample configuration for onos-app-proxyarp.
# This configuration file would be placed at: $(KARAF_ROOT)/etc.
#
# Enable IPv6 Neighbor Discovery.
#
# ipv6NeighborDiscovery = false