Added configuration for PIM interfaces.
Now the PIM application requires PIM Interface configuration for each interface that will have PIM enabled (no longer uses all ONOS interfaces). The interface-specific PIM parameters can be tuned. Change-Id: Ibc284fdbe1b3aa4da48097b3e92470bce4f349a7
Showing
9 changed files
with
549 additions
and
197 deletions
... | @@ -82,37 +82,4 @@ | ... | @@ -82,37 +82,4 @@ |
82 | </dependency> | 82 | </dependency> |
83 | </dependencies> | 83 | </dependencies> |
84 | 84 | ||
85 | - <build> | ||
86 | - <plugins> | ||
87 | - <plugin> | ||
88 | - <groupId>org.apache.felix</groupId> | ||
89 | - <artifactId>maven-bundle-plugin</artifactId> | ||
90 | - <extensions>true</extensions> | ||
91 | - <configuration> | ||
92 | - <instructions> | ||
93 | - <Bundle-SymbolicName> | ||
94 | - ${project.groupId}.${project.artifactId} | ||
95 | - </Bundle-SymbolicName> | ||
96 | - <Import-Package> | ||
97 | - org.slf4j, | ||
98 | - org.osgi.framework, | ||
99 | - com.google.common.*, | ||
100 | - org.apache.karaf.shell.commands, | ||
101 | - org.apache.karaf.shell.console, | ||
102 | - org.onlab.packet.*, | ||
103 | - org.onosproject.*, | ||
104 | - </Import-Package> | ||
105 | - </instructions> | ||
106 | - </configuration> | ||
107 | - </plugin> | ||
108 | - <plugin> | ||
109 | - <groupId>org.apache.maven.plugins</groupId> | ||
110 | - <artifactId>maven-compiler-plugin</artifactId> | ||
111 | - <configuration> | ||
112 | - <source>1.8</source> | ||
113 | - <target>1.8</target> | ||
114 | - </configuration> | ||
115 | - </plugin> | ||
116 | - </plugins> | ||
117 | - </build> | ||
118 | </project> | 85 | </project> | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.pim.cli; | ||
18 | + | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onosproject.cli.AbstractShellCommand; | ||
21 | +import org.onosproject.pim.impl.PIMInterface; | ||
22 | +import org.onosproject.pim.impl.PIMInterfaceService; | ||
23 | + | ||
24 | +import java.util.Set; | ||
25 | + | ||
26 | +/** | ||
27 | + * Lists the interfaces where PIM is enabled. | ||
28 | + */ | ||
29 | +@Command(scope = "onos", name = "pim-interfaces", | ||
30 | + description = "Lists the interfaces where PIM is enabled") | ||
31 | +public class PimInterfacesListCommand extends AbstractShellCommand { | ||
32 | + | ||
33 | + private static final String FORMAT = "interfaceName=%s, holdTime=%s, priority=%s, genId=%s"; | ||
34 | + | ||
35 | + @Override | ||
36 | + protected void execute() { | ||
37 | + PIMInterfaceService interfaceService = get(PIMInterfaceService.class); | ||
38 | + | ||
39 | + Set<PIMInterface> interfaces = interfaceService.getPimInterfaces(); | ||
40 | + | ||
41 | + interfaces.forEach( | ||
42 | + pimIntf -> print(FORMAT, pimIntf.getInterface().name(), | ||
43 | + pimIntf.getHoldtime(), pimIntf.getPriority(), | ||
44 | + pimIntf.getGenerationId())); | ||
45 | + } | ||
46 | + | ||
47 | +} |
... | @@ -24,14 +24,6 @@ import org.onlab.packet.Ethernet; | ... | @@ -24,14 +24,6 @@ import org.onlab.packet.Ethernet; |
24 | import org.onlab.packet.IPv4; | 24 | import org.onlab.packet.IPv4; |
25 | import org.onosproject.core.ApplicationId; | 25 | import org.onosproject.core.ApplicationId; |
26 | import org.onosproject.core.CoreService; | 26 | import org.onosproject.core.CoreService; |
27 | -import org.onosproject.incubator.net.config.basics.ConfigException; | ||
28 | -import org.onosproject.incubator.net.config.basics.InterfaceConfig; | ||
29 | -import org.onosproject.incubator.net.intf.Interface; | ||
30 | -import org.onosproject.incubator.net.intf.InterfaceService; | ||
31 | -import org.onosproject.net.ConnectPoint; | ||
32 | -import org.onosproject.net.config.NetworkConfigEvent; | ||
33 | -import org.onosproject.net.config.NetworkConfigListener; | ||
34 | -import org.onosproject.net.config.NetworkConfigService; | ||
35 | import org.onosproject.net.flow.DefaultTrafficSelector; | 27 | import org.onosproject.net.flow.DefaultTrafficSelector; |
36 | import org.onosproject.net.flow.TrafficSelector; | 28 | import org.onosproject.net.flow.TrafficSelector; |
37 | import org.onosproject.net.mcast.MulticastRouteService; | 29 | import org.onosproject.net.mcast.MulticastRouteService; |
... | @@ -43,7 +35,6 @@ import org.onosproject.net.packet.PacketService; | ... | @@ -43,7 +35,6 @@ import org.onosproject.net.packet.PacketService; |
43 | import org.slf4j.Logger; | 35 | import org.slf4j.Logger; |
44 | 36 | ||
45 | import java.util.Optional; | 37 | import java.util.Optional; |
46 | -import java.util.Set; | ||
47 | 38 | ||
48 | import static org.slf4j.LoggerFactory.getLogger; | 39 | import static org.slf4j.LoggerFactory.getLogger; |
49 | 40 | ||
... | @@ -72,17 +63,6 @@ public class PIMApplication { | ... | @@ -72,17 +63,6 @@ public class PIMApplication { |
72 | // Create an instance of the PIM packet handler | 63 | // Create an instance of the PIM packet handler |
73 | protected PIMPacketHandler pimPacketHandler; | 64 | protected PIMPacketHandler pimPacketHandler; |
74 | 65 | ||
75 | - // Get the network configuration updates | ||
76 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
77 | - protected NetworkConfigService configService; | ||
78 | - | ||
79 | - // Access defined network (IP) interfaces | ||
80 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
81 | - protected InterfaceService interfaceService; | ||
82 | - | ||
83 | - // Internal class used to listen for network configuration changes | ||
84 | - private InternalConfigListener configListener = new InternalConfigListener(); | ||
85 | - | ||
86 | // Provide interfaces to the pimInterface manager as a result of Netconfig updates. | 66 | // Provide interfaces to the pimInterface manager as a result of Netconfig updates. |
87 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 67 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
88 | protected PIMInterfaceService pimInterfaceManager; | 68 | protected PIMInterfaceService pimInterfaceManager; |
... | @@ -94,7 +74,6 @@ public class PIMApplication { | ... | @@ -94,7 +74,6 @@ public class PIMApplication { |
94 | */ | 74 | */ |
95 | @Activate | 75 | @Activate |
96 | public void activate() { | 76 | public void activate() { |
97 | - | ||
98 | // Get our application ID | 77 | // Get our application ID |
99 | appId = coreService.registerApplication("org.onosproject.pim"); | 78 | appId = coreService.registerApplication("org.onosproject.pim"); |
100 | 79 | ||
... | @@ -109,15 +88,9 @@ public class PIMApplication { | ... | @@ -109,15 +88,9 @@ public class PIMApplication { |
109 | packetService.requestPackets(selector.build(), PacketPriority.CONTROL, | 88 | packetService.requestPackets(selector.build(), PacketPriority.CONTROL, |
110 | appId, Optional.empty()); | 89 | appId, Optional.empty()); |
111 | 90 | ||
112 | - // Register for notifications from the Network config & Interface services. | ||
113 | - // We'll use these services to represent "PIMInterfaces" | ||
114 | - | ||
115 | // Get a copy of the PIM Packet Handler | 91 | // Get a copy of the PIM Packet Handler |
116 | pimPacketHandler = new PIMPacketHandler(); | 92 | pimPacketHandler = new PIMPacketHandler(); |
117 | 93 | ||
118 | - // Listen for network configuration changes | ||
119 | - configService.addListener(configListener); | ||
120 | - | ||
121 | log.info("Started"); | 94 | log.info("Started"); |
122 | } | 95 | } |
123 | 96 | ||
... | @@ -180,57 +153,4 @@ public class PIMApplication { | ... | @@ -180,57 +153,4 @@ public class PIMApplication { |
180 | } | 153 | } |
181 | } | 154 | } |
182 | 155 | ||
183 | - /* | ||
184 | - * This class receives all events from the network config services, then hands the | ||
185 | - * event off to the PIMInterfaceManager for proper handling. | ||
186 | - * | ||
187 | - * TODO: should this move to PIMInterfaceManager? | ||
188 | - */ | ||
189 | - private class InternalConfigListener implements NetworkConfigListener { | ||
190 | - | ||
191 | - @Override | ||
192 | - public void event(NetworkConfigEvent event) { | ||
193 | - | ||
194 | - log.debug(event.toString()); | ||
195 | - switch (event.type()) { | ||
196 | - case CONFIG_ADDED: | ||
197 | - case CONFIG_UPDATED: | ||
198 | - | ||
199 | - if (event.configClass() == InterfaceConfig.class) { | ||
200 | - InterfaceConfig config = configService.getConfig( | ||
201 | - (ConnectPoint) event.subject(), | ||
202 | - InterfaceConfig.class); | ||
203 | - | ||
204 | - log.debug("Got a network configuration event"); | ||
205 | - | ||
206 | - // Walk the interfaces and feed them to the PIMInterfaceManager | ||
207 | - Set<Interface> intfs; | ||
208 | - try { | ||
209 | - intfs = config.getInterfaces(); | ||
210 | - for (Interface intf : intfs) { | ||
211 | - pimInterfaceManager.updateInterface(intf); | ||
212 | - } | ||
213 | - } catch (ConfigException e) { | ||
214 | - log.error(e.toString()); | ||
215 | - return; | ||
216 | - } | ||
217 | - } | ||
218 | - break; | ||
219 | - | ||
220 | - case CONFIG_REMOVED: | ||
221 | - if (event.configClass() == InterfaceConfig.class) { | ||
222 | - ConnectPoint cp = (ConnectPoint) event.subject(); | ||
223 | - //assertNotNull(cp); | ||
224 | - pimInterfaceManager.deleteInterface(cp); | ||
225 | - } | ||
226 | - break; | ||
227 | - | ||
228 | - case CONFIG_REGISTERED: | ||
229 | - case CONFIG_UNREGISTERED: | ||
230 | - default: | ||
231 | - log.debug("\tWe are not handling this event type"); | ||
232 | - break; | ||
233 | - } | ||
234 | - } | ||
235 | - } | ||
236 | } | 156 | } | ... | ... |
... | @@ -34,8 +34,10 @@ import org.slf4j.Logger; | ... | @@ -34,8 +34,10 @@ import org.slf4j.Logger; |
34 | import java.nio.ByteBuffer; | 34 | import java.nio.ByteBuffer; |
35 | import java.util.HashMap; | 35 | import java.util.HashMap; |
36 | import java.util.Map; | 36 | import java.util.Map; |
37 | +import java.util.Random; | ||
37 | import java.util.Set; | 38 | import java.util.Set; |
38 | 39 | ||
40 | +import static com.google.common.base.Preconditions.checkArgument; | ||
39 | import static com.google.common.base.Preconditions.checkNotNull; | 41 | import static com.google.common.base.Preconditions.checkNotNull; |
40 | import static org.slf4j.LoggerFactory.getLogger; | 42 | import static org.slf4j.LoggerFactory.getLogger; |
41 | 43 | ||
... | @@ -43,7 +45,7 @@ import static org.slf4j.LoggerFactory.getLogger; | ... | @@ -43,7 +45,7 @@ import static org.slf4j.LoggerFactory.getLogger; |
43 | * PIM Interface represents an ONOS Interface with IP and MAC addresses for | 45 | * PIM Interface represents an ONOS Interface with IP and MAC addresses for |
44 | * a given ConnectPoint. | 46 | * a given ConnectPoint. |
45 | */ | 47 | */ |
46 | -public class PIMInterface { | 48 | +public final class PIMInterface { |
47 | 49 | ||
48 | private final Logger log = getLogger(getClass()); | 50 | private final Logger log = getLogger(getClass()); |
49 | 51 | ||
... | @@ -62,10 +64,10 @@ public class PIMInterface { | ... | @@ -62,10 +64,10 @@ public class PIMInterface { |
62 | private int priority = PIMHelloOption.DEFAULT_PRIORITY; | 64 | private int priority = PIMHelloOption.DEFAULT_PRIORITY; |
63 | 65 | ||
64 | // Our current genid | 66 | // Our current genid |
65 | - private int genid = PIMHelloOption.DEFAULT_GENID; // Needs to be assigned. | 67 | + private final int generationId; |
66 | 68 | ||
67 | // The IP address of the DR | 69 | // The IP address of the DR |
68 | - IpAddress drIpaddress; | 70 | + private IpAddress drIpaddress; |
69 | 71 | ||
70 | // A map of all our PIM neighbors keyed on our neighbors IP address | 72 | // A map of all our PIM neighbors keyed on our neighbors IP address |
71 | private Map<IpAddress, PIMNeighbor> pimNeighbors = new HashMap<>(); | 73 | private Map<IpAddress, PIMNeighbor> pimNeighbors = new HashMap<>(); |
... | @@ -74,14 +76,28 @@ public class PIMInterface { | ... | @@ -74,14 +76,28 @@ public class PIMInterface { |
74 | * Create a PIMInterface from an ONOS Interface. | 76 | * Create a PIMInterface from an ONOS Interface. |
75 | * | 77 | * |
76 | * @param intf the ONOS Interface. | 78 | * @param intf the ONOS Interface. |
79 | + * @param holdTime hold time | ||
80 | + * @param priority priority | ||
81 | + * @param propagationDelay propagation delay | ||
82 | + * @param overrideInterval override interval | ||
83 | + * @param packetService reference to the packet service | ||
77 | */ | 84 | */ |
78 | - public PIMInterface(Interface intf, PacketService packetService) { | 85 | + private PIMInterface(Interface intf, |
86 | + short holdTime, | ||
87 | + int priority, | ||
88 | + short propagationDelay, | ||
89 | + short overrideInterval, | ||
90 | + PacketService packetService) { | ||
91 | + | ||
79 | onosInterface = intf; | 92 | onosInterface = intf; |
80 | outputTreatment = createOutputTreatment(); | 93 | outputTreatment = createOutputTreatment(); |
94 | + this.holdtime = holdTime; | ||
81 | this.packetService = packetService; | 95 | this.packetService = packetService; |
82 | IpAddress ourIp = getIpAddress(); | 96 | IpAddress ourIp = getIpAddress(); |
83 | MacAddress mac = intf.mac(); | 97 | MacAddress mac = intf.mac(); |
84 | 98 | ||
99 | + generationId = new Random().nextInt(); | ||
100 | + | ||
85 | // Create a PIM Neighbor to represent ourselves for DR election. | 101 | // Create a PIM Neighbor to represent ourselves for DR election. |
86 | PIMNeighbor us = new PIMNeighbor(ourIp, mac); | 102 | PIMNeighbor us = new PIMNeighbor(ourIp, mac); |
87 | 103 | ||
... | @@ -178,8 +194,8 @@ public class PIMInterface { | ... | @@ -178,8 +194,8 @@ public class PIMInterface { |
178 | * | 194 | * |
179 | * @return our generation ID | 195 | * @return our generation ID |
180 | */ | 196 | */ |
181 | - public int getGenid() { | 197 | + public int getGenerationId() { |
182 | - return genid; | 198 | + return generationId; |
183 | } | 199 | } |
184 | 200 | ||
185 | /** | 201 | /** |
... | @@ -188,7 +204,6 @@ public class PIMInterface { | ... | @@ -188,7 +204,6 @@ public class PIMInterface { |
188 | * result of a newly created interface. | 204 | * result of a newly created interface. |
189 | */ | 205 | */ |
190 | public void sendHello() { | 206 | public void sendHello() { |
191 | - | ||
192 | // Create the base PIM Packet and mark it a hello packet | 207 | // Create the base PIM Packet and mark it a hello packet |
193 | PIMPacket pimPacket = new PIMPacket(PIM.TYPE_HELLO); | 208 | PIMPacket pimPacket = new PIMPacket(PIM.TYPE_HELLO); |
194 | 209 | ||
... | @@ -199,6 +214,9 @@ public class PIMInterface { | ... | @@ -199,6 +214,9 @@ public class PIMInterface { |
199 | // Create the hello message with options | 214 | // Create the hello message with options |
200 | PIMHello hello = new PIMHello(); | 215 | PIMHello hello = new PIMHello(); |
201 | hello.createDefaultOptions(); | 216 | hello.createDefaultOptions(); |
217 | + hello.addOption(PIMHelloOption.createHoldTime(holdtime)); | ||
218 | + hello.addOption(PIMHelloOption.createPriority(priority)); | ||
219 | + hello.addOption(PIMHelloOption.createGenID(generationId)); | ||
202 | 220 | ||
203 | // Now set the hello option payload | 221 | // Now set the hello option payload |
204 | pimPacket.setPIMPayload(hello); | 222 | pimPacket.setPIMPayload(hello); |
... | @@ -266,7 +284,7 @@ public class PIMInterface { | ... | @@ -266,7 +284,7 @@ public class PIMInterface { |
266 | nbr.refreshTimestamp(); | 284 | nbr.refreshTimestamp(); |
267 | 285 | ||
268 | /* | 286 | /* |
269 | - * the election method will frist determine if an election | 287 | + * the election method will first determine if an election |
270 | * needs to be run, if so it will run the election. The | 288 | * needs to be run, if so it will run the election. The |
271 | * IP address of the DR will be returned. If the IP address | 289 | * IP address of the DR will be returned. If the IP address |
272 | * of the DR is different from what we already have we know a | 290 | * of the DR is different from what we already have we know a |
... | @@ -280,17 +298,17 @@ public class PIMInterface { | ... | @@ -280,17 +298,17 @@ public class PIMInterface { |
280 | } | 298 | } |
281 | 299 | ||
282 | // Run an election if we need to. Return the elected IP address. | 300 | // Run an election if we need to. Return the elected IP address. |
283 | - private IpAddress election(PIMNeighbor nbr, IpAddress drip, int drpri) { | 301 | + private IpAddress election(PIMNeighbor nbr, IpAddress drIp, int drPriority) { |
284 | 302 | ||
285 | - IpAddress nbrip = nbr.getIpaddr(); | 303 | + IpAddress nbrIp = nbr.getIpaddr(); |
286 | - if (nbr.getPriority() > drpri) { | 304 | + if (nbr.getPriority() > drPriority) { |
287 | - return nbrip; | 305 | + return nbrIp; |
288 | } | 306 | } |
289 | 307 | ||
290 | - if (nbrip.compareTo(drip) > 0) { | 308 | + if (nbrIp.compareTo(drIp) > 0) { |
291 | - return nbrip; | 309 | + return nbrIp; |
292 | } | 310 | } |
293 | - return drip; | 311 | + return drIp; |
294 | } | 312 | } |
295 | 313 | ||
296 | /** | 314 | /** |
... | @@ -301,4 +319,105 @@ public class PIMInterface { | ... | @@ -301,4 +319,105 @@ public class PIMInterface { |
301 | public void processJoinPrune(Ethernet ethPkt) { | 319 | public void processJoinPrune(Ethernet ethPkt) { |
302 | // TODO: add Join/Prune processing code. | 320 | // TODO: add Join/Prune processing code. |
303 | } | 321 | } |
322 | + | ||
323 | + /** | ||
324 | + * Returns a builder for a PIM interface. | ||
325 | + * | ||
326 | + * @return PIM interface builder | ||
327 | + */ | ||
328 | + public static Builder builder() { | ||
329 | + return new Builder(); | ||
330 | + } | ||
331 | + | ||
332 | + /** | ||
333 | + * Builder for a PIM interface. | ||
334 | + */ | ||
335 | + public static class Builder { | ||
336 | + private Interface intf; | ||
337 | + private PacketService packetService; | ||
338 | + private short holdtime = PIMHelloOption.DEFAULT_HOLDTIME; | ||
339 | + private int priority = PIMHelloOption.DEFAULT_PRIORITY; | ||
340 | + private short propagationDelay = PIMHelloOption.DEFAULT_PRUNEDELAY; | ||
341 | + private short overrideInterval = PIMHelloOption.DEFAULT_OVERRIDEINTERVAL; | ||
342 | + | ||
343 | + /** | ||
344 | + * Uses the specified ONOS interface. | ||
345 | + * | ||
346 | + * @param intf ONOS interface | ||
347 | + * @return this PIM interface builder | ||
348 | + */ | ||
349 | + public Builder withInterface(Interface intf) { | ||
350 | + this.intf = checkNotNull(intf); | ||
351 | + return this; | ||
352 | + } | ||
353 | + | ||
354 | + /** | ||
355 | + * Sets the reference to the packet service. | ||
356 | + * | ||
357 | + * @param packetService packet service | ||
358 | + * @return this PIM interface builder | ||
359 | + */ | ||
360 | + public Builder withPacketService(PacketService packetService) { | ||
361 | + this.packetService = checkNotNull(packetService); | ||
362 | + return this; | ||
363 | + } | ||
364 | + | ||
365 | + /** | ||
366 | + * Uses the specified hold time. | ||
367 | + * | ||
368 | + * @param holdTime hold time in seconds | ||
369 | + * @return this PIM interface builder | ||
370 | + */ | ||
371 | + public Builder withHoldTime(short holdTime) { | ||
372 | + this.holdtime = holdTime; | ||
373 | + return this; | ||
374 | + } | ||
375 | + | ||
376 | + /** | ||
377 | + * Uses the specified DR priority. | ||
378 | + * | ||
379 | + * @param priority DR priority | ||
380 | + * @return this PIM interface builder | ||
381 | + */ | ||
382 | + public Builder withPriority(int priority) { | ||
383 | + this.priority = priority; | ||
384 | + return this; | ||
385 | + } | ||
386 | + | ||
387 | + /** | ||
388 | + * Uses the specified propagation delay. | ||
389 | + * | ||
390 | + * @param propagationDelay propagation delay in ms | ||
391 | + * @return this PIM interface builder | ||
392 | + */ | ||
393 | + public Builder withPropagationDelay(short propagationDelay) { | ||
394 | + this.propagationDelay = propagationDelay; | ||
395 | + return this; | ||
396 | + } | ||
397 | + | ||
398 | + /** | ||
399 | + * Uses the specified override interval. | ||
400 | + * | ||
401 | + * @param overrideInterval override interval in ms | ||
402 | + * @return this PIM interface builder | ||
403 | + */ | ||
404 | + public Builder withOverrideInterval(short overrideInterval) { | ||
405 | + this.overrideInterval = overrideInterval; | ||
406 | + return this; | ||
407 | + } | ||
408 | + | ||
409 | + /** | ||
410 | + * Builds the PIM interface. | ||
411 | + * | ||
412 | + * @return PIM interface | ||
413 | + */ | ||
414 | + public PIMInterface build() { | ||
415 | + checkArgument(intf != null, "Must provide an interface"); | ||
416 | + checkArgument(packetService != null, "Must provide a packet service"); | ||
417 | + | ||
418 | + return new PIMInterface(intf, holdtime, priority, propagationDelay, | ||
419 | + overrideInterval, packetService); | ||
420 | + } | ||
421 | + | ||
422 | + } | ||
304 | } | 423 | } | ... | ... |
... | @@ -15,6 +15,7 @@ | ... | @@ -15,6 +15,7 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.pim.impl; | 16 | package org.onosproject.pim.impl; |
17 | 17 | ||
18 | +import com.google.common.collect.ImmutableSet; | ||
18 | import com.google.common.collect.Maps; | 19 | import com.google.common.collect.Maps; |
19 | import org.apache.felix.scr.annotations.Activate; | 20 | import org.apache.felix.scr.annotations.Activate; |
20 | import org.apache.felix.scr.annotations.Component; | 21 | import org.apache.felix.scr.annotations.Component; |
... | @@ -23,12 +24,20 @@ import org.apache.felix.scr.annotations.Reference; | ... | @@ -23,12 +24,20 @@ import org.apache.felix.scr.annotations.Reference; |
23 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 24 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
24 | import org.apache.felix.scr.annotations.Service; | 25 | import org.apache.felix.scr.annotations.Service; |
25 | import org.onosproject.incubator.net.intf.Interface; | 26 | import org.onosproject.incubator.net.intf.Interface; |
27 | +import org.onosproject.incubator.net.intf.InterfaceEvent; | ||
28 | +import org.onosproject.incubator.net.intf.InterfaceListener; | ||
26 | import org.onosproject.incubator.net.intf.InterfaceService; | 29 | import org.onosproject.incubator.net.intf.InterfaceService; |
27 | import org.onosproject.net.ConnectPoint; | 30 | import org.onosproject.net.ConnectPoint; |
31 | +import org.onosproject.net.config.ConfigFactory; | ||
32 | +import org.onosproject.net.config.NetworkConfigEvent; | ||
33 | +import org.onosproject.net.config.NetworkConfigListener; | ||
34 | +import org.onosproject.net.config.NetworkConfigRegistry; | ||
35 | +import org.onosproject.net.config.basics.SubjectFactories; | ||
28 | import org.onosproject.net.packet.PacketService; | 36 | import org.onosproject.net.packet.PacketService; |
29 | -import org.onosproject.net.provider.ProviderId; | ||
30 | import org.slf4j.Logger; | 37 | import org.slf4j.Logger; |
38 | + | ||
31 | import java.util.Map; | 39 | import java.util.Map; |
40 | +import java.util.Set; | ||
32 | import java.util.concurrent.Executors; | 41 | import java.util.concurrent.Executors; |
33 | import java.util.concurrent.ScheduledExecutorService; | 42 | import java.util.concurrent.ScheduledExecutorService; |
34 | import java.util.concurrent.TimeUnit; | 43 | import java.util.concurrent.TimeUnit; |
... | @@ -46,8 +55,8 @@ public class PIMInterfaceManager implements PIMInterfaceService { | ... | @@ -46,8 +55,8 @@ public class PIMInterfaceManager implements PIMInterfaceService { |
46 | 55 | ||
47 | private final Logger log = getLogger(getClass()); | 56 | private final Logger log = getLogger(getClass()); |
48 | 57 | ||
49 | - // Create ourselves a provider ID | 58 | + private static final Class<PimInterfaceConfig> PIM_INTERFACE_CONFIG_CLASS = PimInterfaceConfig.class; |
50 | - private static final ProviderId PID = new ProviderId("pim", "org.onosproject.pim"); | 59 | + private static final String PIM_INTERFACE_CONFIG_KEY = "pimInterface"; |
51 | 60 | ||
52 | // Create a Scheduled Executor service to send PIM hellos | 61 | // Create a Scheduled Executor service to send PIM hellos |
53 | private final ScheduledExecutorService helloScheduler = | 62 | private final ScheduledExecutorService helloScheduler = |
... | @@ -55,43 +64,76 @@ public class PIMInterfaceManager implements PIMInterfaceService { | ... | @@ -55,43 +64,76 @@ public class PIMInterfaceManager implements PIMInterfaceService { |
55 | 64 | ||
56 | // Wait for a bout 3 seconds before sending the initial hello messages. | 65 | // Wait for a bout 3 seconds before sending the initial hello messages. |
57 | // TODO: make this tunnable. | 66 | // TODO: make this tunnable. |
58 | - private final long initialHelloDelay = (long) 3; | 67 | + private final long initialHelloDelay = 3; |
59 | 68 | ||
60 | // Send PIM hello packets: 30 seconds. | 69 | // Send PIM hello packets: 30 seconds. |
61 | - private final long pimHelloPeriod = (long) 30; | 70 | + private final long pimHelloPeriod = 30; |
62 | 71 | ||
63 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 72 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
64 | - protected InterfaceService interfaceService; | 73 | + protected PacketService packetService; |
65 | 74 | ||
66 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 75 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
67 | - protected PacketService packetService; | 76 | + protected NetworkConfigRegistry networkConfig; |
77 | + | ||
78 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
79 | + protected InterfaceService interfaceService; | ||
68 | 80 | ||
69 | // Store PIM Interfaces in a map key'd by ConnectPoint | 81 | // Store PIM Interfaces in a map key'd by ConnectPoint |
70 | private final Map<ConnectPoint, PIMInterface> pimInterfaces = Maps.newConcurrentMap(); | 82 | private final Map<ConnectPoint, PIMInterface> pimInterfaces = Maps.newConcurrentMap(); |
71 | 83 | ||
84 | + private final InternalNetworkConfigListener configListener = | ||
85 | + new InternalNetworkConfigListener(); | ||
86 | + private final InternalInterfaceListener interfaceListener = | ||
87 | + new InternalInterfaceListener(); | ||
88 | + | ||
89 | + private final ConfigFactory<ConnectPoint, PimInterfaceConfig> pimConfigFactory | ||
90 | + = new ConfigFactory<ConnectPoint, PimInterfaceConfig>( | ||
91 | + SubjectFactories.CONNECT_POINT_SUBJECT_FACTORY, PIM_INTERFACE_CONFIG_CLASS, | ||
92 | + PIM_INTERFACE_CONFIG_KEY) { | ||
93 | + | ||
94 | + @Override | ||
95 | + public PimInterfaceConfig createConfig() { | ||
96 | + return new PimInterfaceConfig(); | ||
97 | + } | ||
98 | + }; | ||
99 | + | ||
72 | @Activate | 100 | @Activate |
73 | public void activate() { | 101 | public void activate() { |
74 | - // Query the Interface service to see if Interfaces already exist. | 102 | + networkConfig.registerConfigFactory(pimConfigFactory); |
75 | - log.info("Started"); | ||
76 | 103 | ||
77 | - // Create PIM Interfaces for each of the existing ONOS Interfaces. | 104 | + // Create PIM Interfaces for each of the existing configured interfaces. |
78 | - for (Interface intf : interfaceService.getInterfaces()) { | 105 | + Set<ConnectPoint> subjects = networkConfig.getSubjects( |
79 | - pimInterfaces.put(intf.connectPoint(), new PIMInterface(intf, packetService)); | 106 | + ConnectPoint.class, PIM_INTERFACE_CONFIG_CLASS); |
107 | + for (ConnectPoint cp : subjects) { | ||
108 | + PimInterfaceConfig config = networkConfig.getConfig(cp, PIM_INTERFACE_CONFIG_CLASS); | ||
109 | + updateInterface(config); | ||
80 | } | 110 | } |
81 | 111 | ||
112 | + networkConfig.addListener(configListener); | ||
113 | + interfaceService.addListener(interfaceListener); | ||
114 | + | ||
82 | // Schedule the periodic hello sender. | 115 | // Schedule the periodic hello sender. |
83 | helloScheduler.scheduleAtFixedRate(new Runnable() { | 116 | helloScheduler.scheduleAtFixedRate(new Runnable() { |
84 | @Override | 117 | @Override |
85 | public void run() { | 118 | public void run() { |
119 | + try { | ||
86 | for (PIMInterface pif : pimInterfaces.values()) { | 120 | for (PIMInterface pif : pimInterfaces.values()) { |
87 | pif.sendHello(); | 121 | pif.sendHello(); |
88 | } | 122 | } |
123 | + } catch (Exception e) { | ||
124 | + log.warn("exception", e); | ||
125 | + } | ||
89 | } | 126 | } |
90 | }, initialHelloDelay, pimHelloPeriod, TimeUnit.SECONDS); | 127 | }, initialHelloDelay, pimHelloPeriod, TimeUnit.SECONDS); |
128 | + | ||
129 | + log.info("Started"); | ||
91 | } | 130 | } |
92 | 131 | ||
93 | @Deactivate | 132 | @Deactivate |
94 | public void deactivate() { | 133 | public void deactivate() { |
134 | + interfaceService.removeListener(interfaceListener); | ||
135 | + networkConfig.removeListener(configListener); | ||
136 | + networkConfig.unregisterConfigFactory(pimConfigFactory); | ||
95 | 137 | ||
96 | // Shutdown the periodic hello task. | 138 | // Shutdown the periodic hello task. |
97 | helloScheduler.shutdown(); | 139 | helloScheduler.shutdown(); |
... | @@ -100,48 +142,128 @@ public class PIMInterfaceManager implements PIMInterfaceService { | ... | @@ -100,48 +142,128 @@ public class PIMInterfaceManager implements PIMInterfaceService { |
100 | } | 142 | } |
101 | 143 | ||
102 | /** | 144 | /** |
103 | - * Update the ONOS Interface with the new Interface. If the PIMInterface does | 145 | + * Return the PIMInterface that corresponds to the given ConnectPoint. |
104 | - * not exist we'll create a new one and store it. | ||
105 | * | 146 | * |
106 | - * @param intf ONOS Interface. | 147 | + * @param cp The ConnectPoint we want to get the PIMInterface for |
148 | + * @return The PIMInterface if it exists, NULL if it does not exist. | ||
107 | */ | 149 | */ |
108 | @Override | 150 | @Override |
109 | - public void updateInterface(Interface intf) { | 151 | + public PIMInterface getPIMInterface(ConnectPoint cp) { |
110 | - ConnectPoint cp = intf.connectPoint(); | 152 | + PIMInterface pi = pimInterfaces.getOrDefault(cp, null); |
153 | + if (pi == null) { | ||
154 | + log.warn("We have been asked for an Interface we don't have: " + cp.toString()); | ||
155 | + } | ||
156 | + return pi; | ||
157 | + } | ||
158 | + | ||
159 | + @Override | ||
160 | + public Set<PIMInterface> getPimInterfaces() { | ||
161 | + return ImmutableSet.copyOf(pimInterfaces.values()); | ||
162 | + } | ||
163 | + | ||
164 | + private void updateInterface(PimInterfaceConfig config) { | ||
165 | + ConnectPoint cp = config.subject(); | ||
166 | + | ||
167 | + if (!config.isEnabled()) { | ||
168 | + removeInterface(cp); | ||
169 | + return; | ||
170 | + } | ||
171 | + | ||
172 | + String intfName = config.getInterfaceName(); | ||
173 | + Interface intf = interfaceService.getInterfaceByName(cp, intfName); | ||
174 | + | ||
175 | + if (intf == null) { | ||
176 | + log.debug("Interface configuration missing: {}", config.getInterfaceName()); | ||
177 | + return; | ||
178 | + } | ||
179 | + | ||
111 | 180 | ||
112 | log.debug("Updating Interface for " + intf.connectPoint().toString()); | 181 | log.debug("Updating Interface for " + intf.connectPoint().toString()); |
113 | - pimInterfaces.compute(cp, (k, v) -> (v == null) ? | 182 | + pimInterfaces.computeIfAbsent(cp, k -> buildPimInterface(config, intf)); |
114 | - new PIMInterface(intf, packetService) : | 183 | + } |
115 | - v.setInterface(intf)); | 184 | + |
185 | + private void removeInterface(ConnectPoint cp) { | ||
186 | + pimInterfaces.remove(cp); | ||
187 | + } | ||
188 | + | ||
189 | + private PIMInterface buildPimInterface(PimInterfaceConfig config, Interface intf) { | ||
190 | + PIMInterface.Builder builder = PIMInterface.builder() | ||
191 | + .withPacketService(packetService) | ||
192 | + .withInterface(intf); | ||
193 | + | ||
194 | + if (config.getHoldTime().isPresent()) { | ||
195 | + builder.withHoldTime(config.getHoldTime().get()); | ||
196 | + } | ||
197 | + if (config.getPriority().isPresent()) { | ||
198 | + builder.withPriority(config.getPriority().get()); | ||
199 | + } | ||
200 | + if (config.getPropagationDelay().isPresent()) { | ||
201 | + builder.withPropagationDelay(config.getPropagationDelay().get()); | ||
202 | + } | ||
203 | + if (config.getOverrideInterval().isPresent()) { | ||
204 | + builder.withOverrideInterval(config.getOverrideInterval().get()); | ||
205 | + } | ||
206 | + | ||
207 | + return builder.build(); | ||
116 | } | 208 | } |
117 | 209 | ||
118 | /** | 210 | /** |
119 | - * Delete the PIM Interface to the corresponding ConnectPoint. | 211 | + * Listener for network config events. |
120 | - * | ||
121 | - * @param cp The connect point associated with this interface we want to delete | ||
122 | */ | 212 | */ |
123 | - @Override | 213 | + private class InternalNetworkConfigListener implements NetworkConfigListener { |
124 | - public void deleteInterface(ConnectPoint cp) { | ||
125 | 214 | ||
126 | - PIMInterface pi = pimInterfaces.remove(cp); | 215 | + @Override |
127 | - if (pi == null) { | 216 | + public void event(NetworkConfigEvent event) { |
128 | - log.warn("We've been asked to remove an interface we3 don't have: " + cp.toString()); | 217 | + if (event.configClass() != PIM_INTERFACE_CONFIG_CLASS) { |
129 | return; | 218 | return; |
130 | } | 219 | } |
220 | + | ||
221 | + switch (event.type()) { | ||
222 | + case CONFIG_REGISTERED: | ||
223 | + case CONFIG_UNREGISTERED: | ||
224 | + break; | ||
225 | + case CONFIG_ADDED: | ||
226 | + case CONFIG_UPDATED: | ||
227 | + ConnectPoint cp = (ConnectPoint) event.subject(); | ||
228 | + PimInterfaceConfig config = networkConfig.getConfig( | ||
229 | + cp, PIM_INTERFACE_CONFIG_CLASS); | ||
230 | + | ||
231 | + updateInterface(config); | ||
232 | + break; | ||
233 | + case CONFIG_REMOVED: | ||
234 | + removeInterface((ConnectPoint) event.subject()); | ||
235 | + break; | ||
236 | + default: | ||
237 | + break; | ||
238 | + } | ||
239 | + } | ||
131 | } | 240 | } |
132 | 241 | ||
133 | /** | 242 | /** |
134 | - * Return the PIMInterface that corresponds to the given ConnectPoint. | 243 | + * Listener for interface events. |
135 | - * | ||
136 | - * @param cp The ConnectPoint we want to get the PIMInterface for | ||
137 | - * @return The PIMInterface if it exists, NULL if it does not exist. | ||
138 | */ | 244 | */ |
245 | + private class InternalInterfaceListener implements InterfaceListener { | ||
246 | + | ||
139 | @Override | 247 | @Override |
140 | - public PIMInterface getPIMInterface(ConnectPoint cp) { | 248 | + public void event(InterfaceEvent event) { |
141 | - PIMInterface pi = pimInterfaces.getOrDefault(cp, null); | 249 | + switch (event.type()) { |
142 | - if (pi == null) { | 250 | + case INTERFACE_ADDED: |
143 | - log.warn("We have been asked for an Interface we don't have: " + cp.toString()); | 251 | + PimInterfaceConfig config = networkConfig.getConfig( |
252 | + event.subject().connectPoint(), PIM_INTERFACE_CONFIG_CLASS); | ||
253 | + | ||
254 | + if (config != null) { | ||
255 | + updateInterface(config); | ||
256 | + } | ||
257 | + break; | ||
258 | + case INTERFACE_UPDATED: | ||
259 | + break; | ||
260 | + case INTERFACE_REMOVED: | ||
261 | + removeInterface(event.subject().connectPoint()); | ||
262 | + break; | ||
263 | + default: | ||
264 | + break; | ||
265 | + | ||
266 | + } | ||
144 | } | 267 | } |
145 | - return pi; | ||
146 | } | 268 | } |
147 | } | 269 | } | ... | ... |
... | @@ -15,9 +15,10 @@ | ... | @@ -15,9 +15,10 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.pim.impl; | 16 | package org.onosproject.pim.impl; |
17 | 17 | ||
18 | -import org.onosproject.incubator.net.intf.Interface; | ||
19 | import org.onosproject.net.ConnectPoint; | 18 | import org.onosproject.net.ConnectPoint; |
20 | 19 | ||
20 | +import java.util.Set; | ||
21 | + | ||
21 | /** | 22 | /** |
22 | * Define the PIMInterfaceService. PIM will use ONOS Interfaces to | 23 | * Define the PIMInterfaceService. PIM will use ONOS Interfaces to |
23 | * define PIM Interfaces. The PIM Application signed up as a Netconfig | 24 | * define PIM Interfaces. The PIM Application signed up as a Netconfig |
... | @@ -28,25 +29,17 @@ import org.onosproject.net.ConnectPoint; | ... | @@ -28,25 +29,17 @@ import org.onosproject.net.ConnectPoint; |
28 | public interface PIMInterfaceService { | 29 | public interface PIMInterfaceService { |
29 | 30 | ||
30 | /** | 31 | /** |
31 | - * Update the corresponding PIMInterface. If the PIMInterface | ||
32 | - * does not exist it will be created. | ||
33 | - * | ||
34 | - * @param intf ONOS Interface. | ||
35 | - */ | ||
36 | - public void updateInterface(Interface intf); | ||
37 | - | ||
38 | - /** | ||
39 | - * Delete the PIMInterface that corresponds to the given ConnectPoint. | ||
40 | - * | ||
41 | - * @param cp The connect point associated with this interface. | ||
42 | - */ | ||
43 | - public void deleteInterface(ConnectPoint cp); | ||
44 | - | ||
45 | - /** | ||
46 | * Return the PIMInterface associated with the given ConnectPoint. | 32 | * Return the PIMInterface associated with the given ConnectPoint. |
47 | * | 33 | * |
48 | * @param cp The ConnectPoint we want to get the PIMInterface for. | 34 | * @param cp The ConnectPoint we want to get the PIMInterface for. |
49 | * @return the PIMInterface if it exists, NULL if it does not exist. | 35 | * @return the PIMInterface if it exists, NULL if it does not exist. |
50 | */ | 36 | */ |
51 | public PIMInterface getPIMInterface(ConnectPoint cp); | 37 | public PIMInterface getPIMInterface(ConnectPoint cp); |
38 | + | ||
39 | + /** | ||
40 | + * Retrieves the set of all interfaces running PIM. | ||
41 | + * | ||
42 | + * @return set of PIM interfaces | ||
43 | + */ | ||
44 | + Set<PIMInterface> getPimInterfaces(); | ||
52 | } | 45 | } | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.pim.impl; | ||
18 | + | ||
19 | +import org.onosproject.net.ConnectPoint; | ||
20 | +import org.onosproject.net.config.Config; | ||
21 | + | ||
22 | +import java.util.Optional; | ||
23 | + | ||
24 | +/** | ||
25 | + * Configuration for a PIM interface. | ||
26 | + */ | ||
27 | +public class PimInterfaceConfig extends Config<ConnectPoint> { | ||
28 | + | ||
29 | + private static final String INTERFACE_NAME = "interfaceName"; | ||
30 | + private static final String ENABLED = "enabled"; | ||
31 | + private static final String HOLD_TIME = "holdTime"; | ||
32 | + private static final String PRIORITY = "priority"; | ||
33 | + private static final String PROPAGATION_DELAY = "propagationDelay"; | ||
34 | + private static final String OVERRIDE_INTERVAL = "overrideInterval"; | ||
35 | + | ||
36 | + /** | ||
37 | + * Gets the name of the interface. This links the PIM configuration with | ||
38 | + * an existing ONOS interface. | ||
39 | + * | ||
40 | + * @return interface name | ||
41 | + */ | ||
42 | + public String getInterfaceName() { | ||
43 | + return node.path(INTERFACE_NAME).asText(); | ||
44 | + } | ||
45 | + | ||
46 | + /** | ||
47 | + * Returns whether PIM is enabled on the interface or not. | ||
48 | + * | ||
49 | + * @return true if PIM is enabled, otherwise false | ||
50 | + */ | ||
51 | + public boolean isEnabled() { | ||
52 | + return node.path(ENABLED).asBoolean(false); | ||
53 | + } | ||
54 | + | ||
55 | + /** | ||
56 | + * Gets the HELLO hold time of the interface. | ||
57 | + * | ||
58 | + * @return hold time | ||
59 | + */ | ||
60 | + public Optional<Short> getHoldTime() { | ||
61 | + if (node.path(HOLD_TIME).isMissingNode()) { | ||
62 | + return Optional.empty(); | ||
63 | + } | ||
64 | + return Optional.of(Short.parseShort(node.path(HOLD_TIME).asText())); | ||
65 | + } | ||
66 | + | ||
67 | + /** | ||
68 | + * Gets the priority of the interface. | ||
69 | + * | ||
70 | + * @return priority | ||
71 | + */ | ||
72 | + public Optional<Integer> getPriority() { | ||
73 | + if (node.path(PRIORITY).isMissingNode()) { | ||
74 | + return Optional.empty(); | ||
75 | + } | ||
76 | + return Optional.of(node.path(PRIORITY).asInt()); | ||
77 | + } | ||
78 | + | ||
79 | + /** | ||
80 | + * Gets the propagation delay of the interface. | ||
81 | + * | ||
82 | + * @return propagation delay | ||
83 | + */ | ||
84 | + public Optional<Short> getPropagationDelay() { | ||
85 | + if (node.path(PROPAGATION_DELAY).isMissingNode()) { | ||
86 | + return Optional.empty(); | ||
87 | + } | ||
88 | + return Optional.of(Short.parseShort(node.path(PROPAGATION_DELAY).asText())); | ||
89 | + } | ||
90 | + | ||
91 | + /** | ||
92 | + * Gets the override interval of the interface. | ||
93 | + * | ||
94 | + * @return override interval | ||
95 | + */ | ||
96 | + public Optional<Short> getOverrideInterval() { | ||
97 | + if (node.path(OVERRIDE_INTERVAL).isMissingNode()) { | ||
98 | + return Optional.empty(); | ||
99 | + } | ||
100 | + return Optional.of(Short.parseShort(node.path(OVERRIDE_INTERVAL).asText())); | ||
101 | + } | ||
102 | +} |
... | @@ -17,7 +17,7 @@ | ... | @@ -17,7 +17,7 @@ |
17 | 17 | ||
18 | <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0"> | 18 | <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0"> |
19 | <command> | 19 | <command> |
20 | - <action class="org.onosproject.pim.cli.PIMShowCommand"/> | 20 | + <action class="org.onosproject.pim.cli.PimInterfacesListCommand"/> |
21 | </command> | 21 | </command> |
22 | </command-bundle> | 22 | </command-bundle> |
23 | 23 | ... | ... |
... | @@ -23,29 +23,43 @@ import java.text.MessageFormat; | ... | @@ -23,29 +23,43 @@ import java.text.MessageFormat; |
23 | import static org.onlab.packet.PacketUtils.checkBufferLength; | 23 | import static org.onlab.packet.PacketUtils.checkBufferLength; |
24 | import static org.onlab.packet.PacketUtils.checkInput; | 24 | import static org.onlab.packet.PacketUtils.checkInput; |
25 | 25 | ||
26 | +/** | ||
27 | + * PIM HELLO option. | ||
28 | + */ | ||
26 | public class PIMHelloOption { | 29 | public class PIMHelloOption { |
27 | 30 | ||
28 | - /** | 31 | + /* |
29 | * PIM Option types. | 32 | * PIM Option types. |
30 | */ | 33 | */ |
31 | public static final short OPT_HOLDTIME = 1; | 34 | public static final short OPT_HOLDTIME = 1; |
35 | + public static final short HOLDTIME_LENGTH = 2; | ||
36 | + public static final short DEFAULT_HOLDTIME = 105; | ||
37 | + | ||
32 | public static final short OPT_PRUNEDELAY = 2; | 38 | public static final short OPT_PRUNEDELAY = 2; |
33 | - public static final short OPT_PRIORITY = 19; | 39 | + public static final short PRUNEDELAY_LENGTH = 4; |
34 | - public static final short OPT_GENID = 20; | 40 | + public static final short DEFAULT_PRUNEDELAY = 500; // 500 ms |
35 | - public static final short OPT_ADDRLIST = 24; | 41 | + public static final short DEFAULT_OVERRIDEINTERVAL = 2500; // 2500 ms |
36 | 42 | ||
37 | - public static final short DEFAULT_HOLDTIME = 105; | 43 | + public static final short OPT_PRIORITY = 19; |
38 | - public static final int DEFAULT_PRUNEDELAY = 2000; // 2,000 ms | 44 | + public static final short PRIORITY_LENGTH = 4; |
39 | public static final int DEFAULT_PRIORITY = 1; | 45 | public static final int DEFAULT_PRIORITY = 1; |
46 | + | ||
47 | + public static final short OPT_GENID = 20; | ||
48 | + public static final short GENID_LENGTH = 4; | ||
40 | public static final int DEFAULT_GENID = 0; | 49 | public static final int DEFAULT_GENID = 0; |
41 | 50 | ||
51 | + public static final short OPT_ADDRLIST = 24; | ||
52 | + | ||
42 | public static final int MINIMUM_OPTION_LEN_BYTES = 4; | 53 | public static final int MINIMUM_OPTION_LEN_BYTES = 4; |
43 | 54 | ||
44 | // Values for this particular hello option. | 55 | // Values for this particular hello option. |
45 | - private short optType; | 56 | + private short optType = 0; |
46 | - private short optLength; | 57 | + private short optLength = 0; |
47 | private byte[] optValue; | 58 | private byte[] optValue; |
48 | 59 | ||
60 | + /** | ||
61 | + * Constructs a new hello option with no fields set. | ||
62 | + */ | ||
49 | public PIMHelloOption() { | 63 | public PIMHelloOption() { |
50 | } | 64 | } |
51 | 65 | ||
... | @@ -59,25 +73,25 @@ public class PIMHelloOption { | ... | @@ -59,25 +73,25 @@ public class PIMHelloOption { |
59 | this.optType = type; | 73 | this.optType = type; |
60 | switch (type) { | 74 | switch (type) { |
61 | case OPT_HOLDTIME: | 75 | case OPT_HOLDTIME: |
62 | - this.optLength = 2; | 76 | + this.optLength = HOLDTIME_LENGTH; |
63 | this.optValue = new byte[optLength]; | 77 | this.optValue = new byte[optLength]; |
64 | ByteBuffer.wrap(this.optValue).putShort(PIMHelloOption.DEFAULT_HOLDTIME); | 78 | ByteBuffer.wrap(this.optValue).putShort(PIMHelloOption.DEFAULT_HOLDTIME); |
65 | break; | 79 | break; |
66 | 80 | ||
67 | case OPT_PRUNEDELAY: | 81 | case OPT_PRUNEDELAY: |
68 | - this.optLength = 4; | 82 | + this.optLength = PRUNEDELAY_LENGTH; |
69 | this.optValue = new byte[this.optLength]; | 83 | this.optValue = new byte[this.optLength]; |
70 | ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_PRUNEDELAY); | 84 | ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_PRUNEDELAY); |
71 | break; | 85 | break; |
72 | 86 | ||
73 | case OPT_PRIORITY: | 87 | case OPT_PRIORITY: |
74 | - this.optLength = 4; | 88 | + this.optLength = PRIORITY_LENGTH; |
75 | this.optValue = new byte[this.optLength]; | 89 | this.optValue = new byte[this.optLength]; |
76 | ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_PRIORITY); | 90 | ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_PRIORITY); |
77 | break; | 91 | break; |
78 | 92 | ||
79 | case OPT_GENID: | 93 | case OPT_GENID: |
80 | - this.optLength = 4; | 94 | + this.optLength = GENID_LENGTH; |
81 | this.optValue = new byte[this.optLength]; | 95 | this.optValue = new byte[this.optLength]; |
82 | ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_GENID); | 96 | ByteBuffer.wrap(this.optValue).putInt(PIMHelloOption.DEFAULT_GENID); |
83 | break; | 97 | break; |
... | @@ -109,17 +123,85 @@ public class PIMHelloOption { | ... | @@ -109,17 +123,85 @@ public class PIMHelloOption { |
109 | return this.optLength; | 123 | return this.optLength; |
110 | } | 124 | } |
111 | 125 | ||
112 | - public void setValue(ByteBuffer bb) throws DeserializationException { | 126 | + public void setValue(ByteBuffer bb) { |
113 | this.optValue = new byte[this.optLength]; | 127 | this.optValue = new byte[this.optLength]; |
114 | bb.get(this.optValue, 0, this.optLength); | 128 | bb.get(this.optValue, 0, this.optLength); |
115 | } | 129 | } |
116 | 130 | ||
131 | + public void setValue(byte[] value) { | ||
132 | + this.optValue = value; | ||
133 | + } | ||
134 | + | ||
117 | public byte[] getValue() { | 135 | public byte[] getValue() { |
118 | return this.optValue; | 136 | return this.optValue; |
119 | } | 137 | } |
120 | 138 | ||
139 | + /** | ||
140 | + * Creates a new PIM Hello option with the specified values. | ||
141 | + * | ||
142 | + * @param type hello option type | ||
143 | + * @param length option length | ||
144 | + * @param value option value | ||
145 | + * @return new PIM Hello option | ||
146 | + */ | ||
147 | + public static PIMHelloOption create(short type, short length, ByteBuffer value) { | ||
148 | + PIMHelloOption option = new PIMHelloOption(); | ||
149 | + option.setOptType(type); | ||
150 | + option.setOptLength(length); | ||
151 | + value.rewind(); | ||
152 | + option.setValue(value); | ||
153 | + return option; | ||
154 | + } | ||
155 | + | ||
156 | + /** | ||
157 | + * Creates a new priority option. | ||
158 | + * | ||
159 | + * @param priority priority | ||
160 | + * @return priority option | ||
161 | + */ | ||
162 | + public static PIMHelloOption createPriority(int priority) { | ||
163 | + return create(OPT_PRIORITY, PRIORITY_LENGTH, | ||
164 | + ByteBuffer.allocate(PRIORITY_LENGTH).putInt(priority)); | ||
165 | + } | ||
166 | + | ||
167 | + /** | ||
168 | + * Creates a new hold time option. | ||
169 | + * | ||
170 | + * @param holdTime hold time | ||
171 | + * @return hold time option | ||
172 | + */ | ||
173 | + public static PIMHelloOption createHoldTime(short holdTime) { | ||
174 | + return create(OPT_HOLDTIME, HOLDTIME_LENGTH, | ||
175 | + ByteBuffer.allocate(HOLDTIME_LENGTH).putShort(holdTime)); | ||
176 | + } | ||
177 | + | ||
178 | + /** | ||
179 | + * Creates a new generation ID option with a particular generation ID. | ||
180 | + * | ||
181 | + * @param genId generation ID value | ||
182 | + * @return generation ID option | ||
183 | + */ | ||
184 | + public static PIMHelloOption createGenID(int genId) { | ||
185 | + return create(OPT_GENID, GENID_LENGTH, | ||
186 | + ByteBuffer.allocate(GENID_LENGTH).putInt(genId)); | ||
187 | + } | ||
188 | + | ||
189 | + /** | ||
190 | + * Creates a new LAN Prune Delay option. | ||
191 | + * | ||
192 | + * @param propagationDelay prune delay | ||
193 | + * @param overrideInterval override interval | ||
194 | + * @return prune delay option | ||
195 | + */ | ||
196 | + public static PIMHelloOption createPruneDelay(short propagationDelay, short overrideInterval) { | ||
197 | + return create(OPT_PRUNEDELAY, PRUNEDELAY_LENGTH, | ||
198 | + ByteBuffer.allocate(PRUNEDELAY_LENGTH) | ||
199 | + .putShort(propagationDelay) | ||
200 | + .putShort(overrideInterval)); | ||
201 | + } | ||
202 | + | ||
121 | public static PIMHelloOption deserialize(ByteBuffer bb) throws DeserializationException { | 203 | public static PIMHelloOption deserialize(ByteBuffer bb) throws DeserializationException { |
122 | - checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), 4); | 204 | + checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), MINIMUM_OPTION_LEN_BYTES); |
123 | 205 | ||
124 | PIMHelloOption opt = new PIMHelloOption(); | 206 | PIMHelloOption opt = new PIMHelloOption(); |
125 | opt.setOptType(bb.getShort()); | 207 | opt.setOptType(bb.getShort()); |
... | @@ -132,7 +214,7 @@ public class PIMHelloOption { | ... | @@ -132,7 +214,7 @@ public class PIMHelloOption { |
132 | } | 214 | } |
133 | 215 | ||
134 | public byte[] serialize() { | 216 | public byte[] serialize() { |
135 | - int len = 4 + this.optLength; | 217 | + int len = MINIMUM_OPTION_LEN_BYTES + this.optLength; |
136 | ByteBuffer bb = ByteBuffer.allocate(len); | 218 | ByteBuffer bb = ByteBuffer.allocate(len); |
137 | bb.putShort(this.optType); | 219 | bb.putShort(this.optType); |
138 | bb.putShort(this.optLength); | 220 | bb.putShort(this.optLength); | ... | ... |
-
Please register or login to post a comment