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 @@ ...@@ -31,4 +31,11 @@
31 31
32 <description>ONOS simple proxy arp module</description> 32 <description>ONOS simple proxy arp module</description>
33 33
34 + <dependencies>
35 + <dependency>
36 + <groupId>org.osgi</groupId>
37 + <artifactId>org.osgi.compendium</artifactId>
38 + </dependency>
39 + </dependencies>
40 +
34 </project> 41 </project>
......
...@@ -15,9 +15,13 @@ ...@@ -15,9 +15,13 @@
15 */ 15 */
16 package org.onosproject.proxyarp; 16 package org.onosproject.proxyarp;
17 17
18 +import java.util.Dictionary;
19 +
18 import org.apache.felix.scr.annotations.Activate; 20 import org.apache.felix.scr.annotations.Activate;
19 import org.apache.felix.scr.annotations.Component; 21 import org.apache.felix.scr.annotations.Component;
20 import org.apache.felix.scr.annotations.Deactivate; 22 import org.apache.felix.scr.annotations.Deactivate;
23 +import org.apache.felix.scr.annotations.Modified;
24 +import org.apache.felix.scr.annotations.Property;
21 import org.apache.felix.scr.annotations.Reference; 25 import org.apache.felix.scr.annotations.Reference;
22 import org.apache.felix.scr.annotations.ReferenceCardinality; 26 import org.apache.felix.scr.annotations.ReferenceCardinality;
23 import org.onlab.packet.Ethernet; 27 import org.onlab.packet.Ethernet;
...@@ -32,8 +36,10 @@ import org.onosproject.net.packet.PacketPriority; ...@@ -32,8 +36,10 @@ import org.onosproject.net.packet.PacketPriority;
32 import org.onosproject.net.packet.PacketProcessor; 36 import org.onosproject.net.packet.PacketProcessor;
33 import org.onosproject.net.packet.PacketService; 37 import org.onosproject.net.packet.PacketService;
34 import org.onosproject.net.proxyarp.ProxyArpService; 38 import org.onosproject.net.proxyarp.ProxyArpService;
39 +import org.osgi.service.component.ComponentContext;
35 import org.slf4j.Logger; 40 import org.slf4j.Logger;
36 41
42 +import static com.google.common.base.Strings.isNullOrEmpty;
37 import static org.slf4j.LoggerFactory.getLogger; 43 import static org.slf4j.LoggerFactory.getLogger;
38 44
39 /** 45 /**
...@@ -57,9 +63,15 @@ public class ProxyArp { ...@@ -57,9 +63,15 @@ public class ProxyArp {
57 63
58 private ApplicationId appId; 64 private ApplicationId appId;
59 65
66 + @Property(name = "ipv6NeighborDiscovery", boolValue = false,
67 + label = "Enable IPv6 Neighbor Discovery; default is false")
68 + private boolean ipv6NeighborDiscovery = false;
69 +
60 @Activate 70 @Activate
61 - public void activate() { 71 + public void activate(ComponentContext context) {
62 appId = coreService.registerApplication("org.onosproject.proxyarp"); 72 appId = coreService.registerApplication("org.onosproject.proxyarp");
73 + readComponentConfiguration(context);
74 +
63 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 1); 75 packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 1);
64 76
65 TrafficSelector.Builder selectorBuilder = 77 TrafficSelector.Builder selectorBuilder =
...@@ -68,21 +80,23 @@ public class ProxyArp { ...@@ -68,21 +80,23 @@ public class ProxyArp {
68 packetService.requestPackets(selectorBuilder.build(), 80 packetService.requestPackets(selectorBuilder.build(),
69 PacketPriority.CONTROL, appId); 81 PacketPriority.CONTROL, appId);
70 82
71 - // IPv6 Neighbor Solicitation packet. 83 + if (ipv6NeighborDiscovery) {
72 - selectorBuilder = DefaultTrafficSelector.builder(); 84 + // IPv6 Neighbor Solicitation packet.
73 - selectorBuilder.matchEthType(Ethernet.TYPE_IPV6); 85 + selectorBuilder = DefaultTrafficSelector.builder();
74 - selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6); 86 + selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
75 - selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION); 87 + selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
76 - packetService.requestPackets(selectorBuilder.build(), 88 + selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
77 - PacketPriority.CONTROL, appId); 89 + packetService.requestPackets(selectorBuilder.build(),
78 - 90 + PacketPriority.CONTROL, appId);
79 - // IPv6 Neighbor Advertisement packet. 91 +
80 - selectorBuilder = DefaultTrafficSelector.builder(); 92 + // IPv6 Neighbor Advertisement packet.
81 - selectorBuilder.matchEthType(Ethernet.TYPE_IPV6); 93 + selectorBuilder = DefaultTrafficSelector.builder();
82 - selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6); 94 + selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
83 - selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT); 95 + selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
84 - packetService.requestPackets(selectorBuilder.build(), 96 + selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
85 - PacketPriority.CONTROL, appId); 97 + packetService.requestPackets(selectorBuilder.build(),
98 + PacketPriority.CONTROL, appId);
99 + }
86 100
87 log.info("Started with Application ID {}", appId.id()); 101 log.info("Started with Application ID {}", appId.id());
88 } 102 }
...@@ -94,6 +108,50 @@ public class ProxyArp { ...@@ -94,6 +108,50 @@ public class ProxyArp {
94 log.info("Stopped"); 108 log.info("Stopped");
95 } 109 }
96 110
111 + @Modified
112 + public void modified(ComponentContext context) {
113 + readComponentConfiguration(context);
114 + }
115 +
116 + /**
117 + * Extracts properties from the component configuration context.
118 + *
119 + * @param context the component context
120 + */
121 + private void readComponentConfiguration(ComponentContext context) {
122 + Dictionary<?, ?> properties = context.getProperties();
123 + Boolean flag;
124 +
125 + flag = isPropertyEnabled(properties, "ipv6NeighborDiscovery");
126 + if (flag == null) {
127 + log.info("IPv6 Neighbor Discovery is not configured, " +
128 + "using current value of {}", ipv6NeighborDiscovery);
129 + } else {
130 + ipv6NeighborDiscovery = flag;
131 + log.info("Configured. IPv6 Neighbor Discovery is {}",
132 + ipv6NeighborDiscovery ? "enabled" : "disabled");
133 + }
134 + }
135 +
136 + /**
137 + * Check property name is defined and set to true.
138 + *
139 + * @param properties properties to be looked up
140 + * @param propertyName the name of the property to look up
141 + * @return value when the propertyName is defined or return null
142 + */
143 + private static Boolean isPropertyEnabled(Dictionary<?, ?> properties,
144 + String propertyName) {
145 + Boolean value = null;
146 + try {
147 + String s = (String) properties.get(propertyName);
148 + value = isNullOrEmpty(s) ? null : s.trim().equals("true");
149 + } catch (ClassCastException e) {
150 + // No propertyName defined.
151 + value = null;
152 + }
153 + return value;
154 + }
97 155
98 /** 156 /**
99 * Packet processor responsible for forwarding packets along their paths. 157 * Packet processor responsible for forwarding packets along their paths.
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.provider.host.impl; 16 package org.onosproject.provider.host.impl;
17 17
18 +import static com.google.common.base.Strings.isNullOrEmpty;
18 import static org.slf4j.LoggerFactory.getLogger; 19 import static org.slf4j.LoggerFactory.getLogger;
19 20
20 import java.util.Dictionary; 21 import java.util.Dictionary;
...@@ -103,6 +104,10 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -103,6 +104,10 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
103 label = "Enable host removal on port/device down events") 104 label = "Enable host removal on port/device down events")
104 private boolean hostRemovalEnabled = true; 105 private boolean hostRemovalEnabled = true;
105 106
107 + @Property(name = "ipv6NeighborDiscovery", boolValue = false,
108 + label = "Enable using IPv6 Neighbor Discovery by the " +
109 + "Host Location Provider; default is false")
110 + private boolean ipv6NeighborDiscovery = false;
106 111
107 /** 112 /**
108 * Creates an OpenFlow host provider. 113 * Creates an OpenFlow host provider.
...@@ -115,8 +120,8 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -115,8 +120,8 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
115 public void activate(ComponentContext context) { 120 public void activate(ComponentContext context) {
116 appId = 121 appId =
117 coreService.registerApplication("org.onosproject.provider.host"); 122 coreService.registerApplication("org.onosproject.provider.host");
123 + readComponentConfiguration(context);
118 124
119 - modified(context);
120 providerService = providerRegistry.register(this); 125 providerService = providerRegistry.register(this);
121 packetService.addProcessor(processor, 1); 126 packetService.addProcessor(processor, 1);
122 deviceService.addListener(deviceListener); 127 deviceService.addListener(deviceListener);
...@@ -127,21 +132,23 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -127,21 +132,23 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
127 packetService.requestPackets(selectorBuilder.build(), 132 packetService.requestPackets(selectorBuilder.build(),
128 PacketPriority.CONTROL, appId); 133 PacketPriority.CONTROL, appId);
129 134
130 - // IPv6 Neighbor Solicitation packet. 135 + if (ipv6NeighborDiscovery) {
131 - selectorBuilder = DefaultTrafficSelector.builder(); 136 + // IPv6 Neighbor Solicitation packet.
132 - selectorBuilder.matchEthType(Ethernet.TYPE_IPV6); 137 + selectorBuilder = DefaultTrafficSelector.builder();
133 - selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6); 138 + selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
134 - selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION); 139 + selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
135 - packetService.requestPackets(selectorBuilder.build(), 140 + selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
136 - PacketPriority.CONTROL, appId); 141 + packetService.requestPackets(selectorBuilder.build(),
137 - 142 + PacketPriority.CONTROL, appId);
138 - // IPv6 Neighbor Advertisement packet. 143 +
139 - selectorBuilder = DefaultTrafficSelector.builder(); 144 + // IPv6 Neighbor Advertisement packet.
140 - selectorBuilder.matchEthType(Ethernet.TYPE_IPV6); 145 + selectorBuilder = DefaultTrafficSelector.builder();
141 - selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6); 146 + selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
142 - selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT); 147 + selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
143 - packetService.requestPackets(selectorBuilder.build(), 148 + selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
144 - PacketPriority.CONTROL, appId); 149 + packetService.requestPackets(selectorBuilder.build(),
150 + PacketPriority.CONTROL, appId);
151 + }
145 152
146 log.info("Started with Application ID {}", appId.id()); 153 log.info("Started with Application ID {}", appId.id());
147 } 154 }
...@@ -157,17 +164,57 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -157,17 +164,57 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
157 164
158 @Modified 165 @Modified
159 public void modified(ComponentContext context) { 166 public void modified(ComponentContext context) {
160 - Dictionary properties = context.getProperties(); 167 + readComponentConfiguration(context);
168 + }
169 +
170 + /**
171 + * Extracts properties from the component configuration context.
172 + *
173 + * @param context the component context
174 + */
175 + private void readComponentConfiguration(ComponentContext context) {
176 + Dictionary<?, ?> properties = context.getProperties();
177 + Boolean flag;
178 +
179 + flag = isPropertyEnabled(properties, "hostRemovalEnabled");
180 + if (flag == null) {
181 + log.info("Host removal on port/device down events is not configured, " +
182 + "using current value of {}", hostRemovalEnabled);
183 + } else {
184 + hostRemovalEnabled = flag;
185 + log.info("Configured. Host removal on port/device down events is {}",
186 + hostRemovalEnabled ? "enabled" : "disabled");
187 + }
188 +
189 + flag = isPropertyEnabled(properties, "ipv6NeighborDiscovery");
190 + if (flag == null) {
191 + log.info("Using IPv6 Neighbor Discovery is not configured, " +
192 + "using current value of {}", ipv6NeighborDiscovery);
193 + } else {
194 + ipv6NeighborDiscovery = flag;
195 + log.info("Configured. Using IPv6 Neighbor Discovery is {}",
196 + ipv6NeighborDiscovery ? "enabled" : "disabled");
197 + }
198 + }
199 +
200 + /**
201 + * Check property name is defined and set to true.
202 + *
203 + * @param properties properties to be looked up
204 + * @param propertyName the name of the property to look up
205 + * @return value when the propertyName is defined or return null
206 + */
207 + private static Boolean isPropertyEnabled(Dictionary<?, ?> properties,
208 + String propertyName) {
209 + Boolean value = null;
161 try { 210 try {
162 - String flag = (String) properties.get("hostRemovalEnabled"); 211 + String s = (String) properties.get(propertyName);
163 - if (flag != null) { 212 + value = isNullOrEmpty(s) ? null : s.trim().equals("true");
164 - hostRemovalEnabled = flag.equals("true");
165 - }
166 } catch (ClassCastException e) { 213 } catch (ClassCastException e) {
167 - hostRemovalEnabled = true; 214 + // No propertyName defined.
215 + value = null;
168 } 216 }
169 - log.info("Host removal is {}", 217 + return value;
170 - hostRemovalEnabled ? "enabled" : "disabled");
171 } 218 }
172 219
173 @Override 220 @Override
......
1 +#
2 +# Sample configuration for Host Location Provider
3 +# This configuration file would be placed at: $(KARAF_ROOT)/etc.
4 +
5 +#
6 +# Enable host removal on port/device down events.
7 +#
8 +# hostRemovalEnabled = true
9 +
10 +#
11 +# Enable using IPv6 Neighbor Discovery by the Host Location Provider.
12 +#
13 +# ipv6NeighborDiscovery = false
1 +#
2 +# Sample configuration for onos-app-proxyarp.
3 +# This configuration file would be placed at: $(KARAF_ROOT)/etc.
4 +
5 +#
6 +# Enable IPv6 Neighbor Discovery.
7 +#
8 +# ipv6NeighborDiscovery = false