Rusty Eddy
Committed by Gerrit Code Review

PIM Neighbors refactored to PIMInterfaces and now used

the NetworkConfiguration service

Change-Id: Ieb0a6faee3f3399f1bba5d9614fce6b0050e8510
...@@ -18,30 +18,30 @@ package org.onosproject.pim.cli; ...@@ -18,30 +18,30 @@ package org.onosproject.pim.cli;
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
19 import org.apache.karaf.shell.commands.Command; 19 import org.apache.karaf.shell.commands.Command;
20 import org.onosproject.cli.AbstractShellCommand; 20 import org.onosproject.cli.AbstractShellCommand;
21 -import org.onosproject.net.ConnectPoint; 21 +import org.onosproject.pim.impl.PIMInterface;
22 -import org.onosproject.pim.impl.PIMNeighbors; 22 +import org.onosproject.pim.impl.PIMInterfaces;
23 -import org.onosproject.pim.impl.PIMNeighborsCodec; 23 +import org.onosproject.pim.impl.PIMInterfacesCodec;
24 24
25 -import java.util.HashMap; 25 +import java.util.Collection;
26 26
27 -@Command(scope = "onos", name = "pim-neighbors", description = "Displays the pim neighbors") 27 +@Command(scope = "onos", name = "pim-interfaces", description = "Displays the pim interfaces")
28 public class PIMShowCommand extends AbstractShellCommand { 28 public class PIMShowCommand extends AbstractShellCommand {
29 29
30 // prints either the json or cli version of the hash map connect point 30 // prints either the json or cli version of the hash map connect point
31 - // neighbors from the PIMNeighbors class. 31 + // neighbors from the PIMInterfaces class.
32 @Override 32 @Override
33 protected void execute() { 33 protected void execute() {
34 // grab connect point neighbors hash map to send in to json encoder. 34 // grab connect point neighbors hash map to send in to json encoder.
35 - HashMap<ConnectPoint, PIMNeighbors> pimNbrs = PIMNeighbors.getConnectPointNeighbors(); 35 + Collection<PIMInterface> pimIntfs = PIMInterfaces.getInstance().getInterfaces();
36 if (outputJson()) { 36 if (outputJson()) {
37 - print("%s", json(pimNbrs)); 37 + print("%s", json(pimIntfs));
38 } else { 38 } else {
39 - print(PIMNeighbors.printPimNeighbors()); 39 + print(PIMInterfaces.getInstance().printInterfaces());
40 } 40 }
41 } 41 }
42 42
43 - private JsonNode json(HashMap<ConnectPoint, PIMNeighbors> pimNbrs) { 43 + private JsonNode json(Collection<PIMInterface> pimIntfs) {
44 - return new PIMNeighborsCodec().encode(pimNbrs, this); 44 + return new PIMInterfacesCodec().encode(pimIntfs, this);
45 } 45 }
46 46
47 } 47 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -22,132 +22,61 @@ import org.apache.felix.scr.annotations.Component; ...@@ -22,132 +22,61 @@ import org.apache.felix.scr.annotations.Component;
22 import org.apache.felix.scr.annotations.Deactivate; 22 import org.apache.felix.scr.annotations.Deactivate;
23 import org.apache.felix.scr.annotations.Reference; 23 import org.apache.felix.scr.annotations.Reference;
24 import org.apache.felix.scr.annotations.ReferenceCardinality; 24 import org.apache.felix.scr.annotations.ReferenceCardinality;
25 -import org.onlab.packet.Ethernet;
26 -import org.onlab.packet.IPv4;
27 -import org.onlab.packet.Ip4Address;
28 -import org.onlab.packet.IpAddress;
29 -import org.onlab.packet.IpPrefix;
30 -import org.onlab.packet.PIM;
31 import org.onosproject.core.ApplicationId; 25 import org.onosproject.core.ApplicationId;
32 import org.onosproject.core.CoreService; 26 import org.onosproject.core.CoreService;
33 -import org.onosproject.net.flow.DefaultTrafficSelector; 27 +import org.onosproject.incubator.net.intf.InterfaceService;
34 -import org.onosproject.net.flow.TrafficSelector; 28 +import org.onosproject.net.config.NetworkConfigService;
35 -import org.onosproject.net.packet.InboundPacket;
36 -import org.onosproject.net.packet.PacketContext;
37 -import org.onosproject.net.packet.PacketPriority;
38 -import org.onosproject.net.packet.PacketProcessor;
39 import org.onosproject.net.packet.PacketService; 29 import org.onosproject.net.packet.PacketService;
40 import org.slf4j.Logger; 30 import org.slf4j.Logger;
41 31
42 /** 32 /**
43 - * Protocol Independent Multicast Emulation. 33 + * Protocol Independent Multicast (PIM) Emulation. This component is responsible
34 + * for reference the services this PIM module is going to need, then initializing
35 + * the corresponding utility classes.
44 */ 36 */
45 @Component(immediate = true) 37 @Component(immediate = true)
46 public class PIMComponent { 38 public class PIMComponent {
47 private final Logger log = getLogger(getClass()); 39 private final Logger log = getLogger(getClass());
48 40
41 + // Register to receive PIM packets, used to send packets as well
49 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 42 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
50 protected PacketService packetService; 43 protected PacketService packetService;
51 44
45 + // Get the appId
52 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 46 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 protected CoreService coreService; 47 protected CoreService coreService;
54 48
55 - private PIMPacketProcessor processor = new PIMPacketProcessor(); 49 + // Get the network configuration updates
50 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
51 + protected NetworkConfigService configService;
52 +
53 + // Access defined network (IP) interfaces
54 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
55 + protected InterfaceService interfaceService;
56 +
56 private static ApplicationId appId; 57 private static ApplicationId appId;
57 58
59 + private PIMInterfaces pimInterfaces;
60 + private PIMPacketHandler pimPacketHandler;
61 +
58 @Activate 62 @Activate
59 public void activate() { 63 public void activate() {
60 appId = coreService.registerApplication("org.onosproject.pim"); 64 appId = coreService.registerApplication("org.onosproject.pim");
61 65
62 - packetService.addProcessor(processor, PacketProcessor.director(1)); 66 + // Initialize the Packet Handler class
67 + pimPacketHandler = PIMPacketHandler.getInstance();
68 + pimPacketHandler.initialize(packetService, appId);
63 69
64 - // Build a traffic selector for all multicast traffic 70 + // Initialize the Interface class
65 - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); 71 + pimInterfaces = PIMInterfaces.getInstance();
66 - selector.matchEthType(Ethernet.TYPE_IPV4); 72 + pimInterfaces.initialize(configService, interfaceService);
67 - selector.matchIPProtocol(IPv4.PROTOCOL_PIM);
68 - packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
69 73
70 log.info("Started"); 74 log.info("Started");
71 } 75 }
72 76
73 @Deactivate 77 @Deactivate
74 public void deactivate() { 78 public void deactivate() {
75 - packetService.removeProcessor(processor); 79 + PIMPacketHandler.getInstance().stop();
76 - processor = null;
77 log.info("Stopped"); 80 log.info("Stopped");
78 } 81 }
79 -
80 - /**
81 - * Packet processor responsible for handling IGMP packets.
82 - */
83 - private class PIMPacketProcessor implements PacketProcessor {
84 -
85 - @Override
86 - public void process(PacketContext context) {
87 - // Stop processing if the packet has been handled, since we
88 - // can't do any more to it.
89 - if (context.isHandled()) {
90 - return;
91 - }
92 -
93 - InboundPacket pkt = context.inPacket();
94 - if (pkt == null) {
95 - return;
96 - }
97 -
98 - Ethernet ethPkt = pkt.parsed();
99 - if (ethPkt == null) {
100 - return;
101 - }
102 -
103 - /*
104 - * IPv6 MLD packets are handled by ICMP6. We'll only deal
105 - * with IPv4.
106 - */
107 - if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) {
108 - return;
109 - }
110 -
111 - IPv4 ip = (IPv4) ethPkt.getPayload();
112 - IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress());
113 - IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress());
114 - log.debug("Packet (" + saddr.toString() + ", " + gaddr.toString() +
115 - "\tingress port: " + context.inPacket().receivedFrom().toString());
116 -
117 - if (ip.getProtocol() != IPv4.PROTOCOL_PIM) {
118 - log.debug("PIM Picked up a non PIM packet: IP protocol: " + ip.getProtocol());
119 - return;
120 - }
121 -
122 - // TODO: check incoming to be PIM.PIM_ADDRESS or "Our" address.
123 - IpPrefix spfx = IpPrefix.valueOf(saddr, 32);
124 - IpPrefix gpfx = IpPrefix.valueOf(gaddr, 32);
125 -
126 - PIM pim = (PIM) ip.getPayload();
127 - switch (pim.getPimMsgType()) {
128 -
129 - case PIM.TYPE_HELLO:
130 - PIMNeighbors.processHello(ethPkt, context.inPacket().receivedFrom());
131 - break;
132 -
133 - case PIM.TYPE_JOIN_PRUNE_REQUEST:
134 - // Create the function
135 - break;
136 -
137 - case PIM.TYPE_ASSERT:
138 - case PIM.TYPE_BOOTSTRAP:
139 - case PIM.TYPE_CANDIDATE_RP_ADV:
140 - case PIM.TYPE_GRAFT:
141 - case PIM.TYPE_GRAFT_ACK:
142 - case PIM.TYPE_REGISTER:
143 - case PIM.TYPE_REGISTER_STOP:
144 - log.debug("Unsupported PIM message type: " + pim.getPimMsgType());
145 - break;
146 -
147 - default:
148 - log.debug("Unkown PIM message type: " + pim.getPimMsgType());
149 - break;
150 - }
151 - }
152 - }
153 } 82 }
......
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.pim.impl;
17 +
18 +import org.onlab.packet.Ethernet;
19 +import org.onlab.packet.IPv4;
20 +import org.onlab.packet.Ip4Address;
21 +import org.onlab.packet.IpAddress;
22 +import org.onlab.packet.MacAddress;
23 +import org.onlab.packet.PIM;
24 +import org.onlab.packet.pim.PIMHello;
25 +import org.onlab.packet.pim.PIMHelloOption;
26 +import org.onosproject.incubator.net.intf.Interface;
27 +import org.onosproject.net.ConnectPoint;
28 +import org.onosproject.net.host.InterfaceIpAddress;
29 +import org.slf4j.Logger;
30 +import org.slf4j.LoggerFactory;
31 +
32 +import java.util.Collection;
33 +import java.util.HashMap;
34 +import java.util.Map;
35 +
36 +import static com.google.common.base.Preconditions.checkNotNull;
37 +
38 +/**
39 + * The PIM Interface is a wrapper around a ConnectPoint and used to provide
40 + * hello options values when "talking" with PIM other PIM routers.
41 + */
42 +public class PIMInterface {
43 + private static Logger log = LoggerFactory.getLogger("PIMInterfaces");
44 +
45 + // Interface from the interface subsystem
46 + private Interface theInterface;
47 +
48 + // The list of PIM neighbors adjacent to this interface
49 + private Map<IpAddress, PIMNeighbor> neighbors = new HashMap<>();
50 +
51 + // The designatedRouter for this LAN
52 + private PIMNeighbor designatedRouter;
53 +
54 + // The priority we use on this ConnectPoint.
55 + private int priority = PIMHelloOption.DEFAULT_PRIORITY;
56 +
57 + // The holdtime we are sending out.
58 + private int holdtime = PIMHelloOption.DEFAULT_HOLDTIME;
59 +
60 + // Then generation ID we are sending out. 0 means we need to generate a new random ID
61 + private int genid = PIMHelloOption.DEFAULT_GENID;
62 +
63 + // Our default prune delay
64 + private int prunedelay = PIMHelloOption.DEFAULT_PRUNEDELAY;
65 +
66 + /**
67 + * Create a PIMInterface.
68 + */
69 + public PIMInterface(Interface intf) {
70 +
71 + log.debug("Adding an interface: " + intf.toString() + "\n");
72 + this.theInterface = intf;
73 +
74 + // Send a hello to let our neighbors know we are alive
75 + sendHello();
76 + }
77 +
78 + /**
79 + * Get the PIM Interface.
80 + *
81 + * @return the PIM Interface
82 + */
83 + public Interface getInterface() {
84 + return theInterface;
85 + }
86 +
87 + /**
88 + * Getter for our IP address.
89 + *
90 + * @return our IP address.
91 + */
92 + public IpAddress getIpAddress() {
93 + if (theInterface.ipAddresses().isEmpty()) {
94 + return null;
95 + }
96 +
97 + // We will just assume the first interface on the list
98 + IpAddress ipaddr = null;
99 + for (InterfaceIpAddress ifipaddr : theInterface.ipAddresses()) {
100 + ipaddr = ifipaddr.ipAddress();
101 + break;
102 + }
103 + return ipaddr;
104 + }
105 +
106 + /**
107 + * Get our priority.
108 + *
109 + * @return our priority.
110 + */
111 + public int getPriority() {
112 + return this.priority;
113 + }
114 +
115 + /**
116 + * Get the designated router on this connection.
117 + *
118 + * @return the PIMNeighbor representing the DR
119 + */
120 + public PIMNeighbor getDesignatedRouter() {
121 + return designatedRouter;
122 + }
123 +
124 + /**
125 + * Are we the DR on this CP?
126 + *
127 + * @return true if we are, false if not
128 + */
129 + public boolean areWeDr() {
130 + return (designatedRouter != null &&
131 + designatedRouter.getPrimaryAddr().equals(this.getIpAddress()));
132 + }
133 +
134 + /**
135 + * Return a collection of PIM Neighbors.
136 + *
137 + * @return the collection of PIM Neighbors
138 + */
139 + public Collection<PIMNeighbor> getNeighbors() {
140 + return this.neighbors.values();
141 + }
142 +
143 + /**
144 + * Find the neighbor with the given IP address on this CP.
145 + *
146 + * @param ipaddr the IP address of the neighbor we are interested in
147 + * @return the pim neighbor if it exists
148 + */
149 + public PIMNeighbor findNeighbor(IpAddress ipaddr) {
150 + PIMNeighbor nbr = neighbors.get(ipaddr);
151 + return nbr;
152 + }
153 +
154 + /**
155 + * Add a new PIM neighbor to this list.
156 + *
157 + * @param nbr the neighbor to be added.
158 + */
159 + public void addNeighbor(PIMNeighbor nbr) {
160 + if (neighbors.containsKey(nbr.getPrimaryAddr())) {
161 +
162 + log.debug("We are adding a neighbor that already exists: {}", nbr.toString());
163 + neighbors.remove(nbr.getPrimaryAddr());
164 + }
165 + neighbors.put(nbr.getPrimaryAddr(), nbr);
166 + }
167 +
168 + /**
169 + * Remove the neighbor from our neighbor list.
170 + *
171 + * @param ipaddr the IP address of the neighbor to remove
172 + */
173 + public void removeNeighbor(IpAddress ipaddr) {
174 +
175 + if (neighbors.containsKey(ipaddr)) {
176 + neighbors.remove(ipaddr);
177 + }
178 + this.electDR();
179 + }
180 +
181 + /**
182 + * Remove the given neighbor from the neighbor list.
183 + *
184 + * @param nbr the nbr to be removed.
185 + */
186 + public void removeNeighbor(PIMNeighbor nbr) {
187 +
188 + neighbors.remove(nbr.getPrimaryAddr(), nbr);
189 + this.electDR();
190 + }
191 +
192 + /**
193 + * Elect a new DR on this ConnectPoint.
194 + *
195 + * @return the PIM Neighbor that wins
196 + */
197 + public PIMNeighbor electDR() {
198 +
199 + for (PIMNeighbor nbr : this.neighbors.values()) {
200 + if (this.designatedRouter == null) {
201 + this.designatedRouter = nbr;
202 + continue;
203 + }
204 +
205 + if (nbr.getPriority() > this.designatedRouter.getPriority()) {
206 + this.designatedRouter = nbr;
207 + continue;
208 + }
209 +
210 + // We could sort in ascending order
211 + if (this.designatedRouter.getPrimaryAddr().compareTo(nbr.getPrimaryAddr()) > 0) {
212 + this.designatedRouter = nbr;
213 + continue;
214 + }
215 + }
216 +
217 + return this.designatedRouter;
218 + }
219 +
220 + /**
221 + * Elect a new DR given the new neighbor.
222 + *
223 + * @param nbr the new neighbor to use in DR election.
224 + * @return the PIM Neighbor that wins DR election
225 + */
226 + public PIMNeighbor electDR(PIMNeighbor nbr) {
227 +
228 + // Make sure I have
229 + if (this.designatedRouter == null ||
230 + this.designatedRouter.getPriority() < nbr.getPriority() ||
231 + this.designatedRouter.getPrimaryAddr().compareTo(nbr.getPrimaryAddr()) > 0) {
232 + this.designatedRouter = nbr;
233 + }
234 + return this.designatedRouter;
235 + }
236 +
237 + /**
238 + * Find or create a pim neighbor with a given ip address and connect point.
239 + *
240 + * @param ipaddr of the pim neighbor
241 + * @param mac The mac address of our sending neighbor
242 + * @return an existing or new PIM neighbor
243 + */
244 + public PIMNeighbor findOrCreate(IpAddress ipaddr, MacAddress mac) {
245 + PIMNeighbor nbr = this.findNeighbor(ipaddr);
246 + if (nbr == null) {
247 + nbr = new PIMNeighbor(ipaddr, mac, this);
248 + this.addNeighbor(nbr);
249 + this.electDR(nbr);
250 + }
251 + return nbr;
252 + }
253 +
254 + /**
255 + * Process a hello packet received on this Interface.
256 + *
257 + * @param ethPkt the ethernet packet containing the hello message
258 + * @param cp the ConnectPoint of this interface
259 + */
260 + public void processHello(Ethernet ethPkt, ConnectPoint cp) {
261 + checkNotNull(ethPkt);
262 + checkNotNull(cp);
263 +
264 + MacAddress srcmac = ethPkt.getSourceMAC();
265 + IPv4 ip = (IPv4) ethPkt.getPayload();
266 + Ip4Address srcip = Ip4Address.valueOf(ip.getSourceAddress());
267 +
268 + PIM pim = (PIM) ip.getPayload();
269 + checkNotNull(pim);
270 +
271 + PIMHello hello = (PIMHello) pim.getPayload();
272 + checkNotNull(hello);
273 +
274 + PIMNeighbor nbr = this.findOrCreate(srcip, srcmac);
275 + if (nbr == null) {
276 + log.error("Could not create a neighbor for: {1}", srcip.toString());
277 + return;
278 + }
279 +
280 + ConnectPoint icp = theInterface.connectPoint();
281 + checkNotNull(icp);
282 + if (!cp.equals(icp)) {
283 + log.error("PIM Hello message received from {} on incorrect interface {}",
284 + nbr.getPrimaryAddr(), this.toString());
285 + return;
286 + }
287 + nbr.refresh(hello);
288 + }
289 +
290 + /**
291 + * Send a hello packet from this interface.
292 + */
293 + public void sendHello() {
294 + PIM pim = new PIM();
295 + PIMHello hello = new PIMHello();
296 +
297 + // Create a PIM Hello
298 + pim = new PIM();
299 + pim.setVersion((byte) 2);
300 + pim.setPIMType((byte) PIM.TYPE_HELLO);
301 + pim.setChecksum((short) 0);
302 +
303 + hello = new PIMHello();
304 + hello.createDefaultOptions();
305 + pim.setPayload(hello);
306 + hello.setParent(pim);
307 +
308 + log.debug("Sending hello: \n");
309 + PIMPacketHandler.getInstance().sendPacket(pim, this);
310 + }
311 +
312 + /**
313 + * prints the connectPointNeighbors list with each neighbor list.
314 + *
315 + * @return string of neighbors.
316 + */
317 + public String printNeighbors() {
318 + String out = "PIM Neighbors Table: \n";
319 + for (PIMNeighbor nbr : this.neighbors.values()) {
320 + out += "\t" + nbr.toString();
321 + }
322 + return out;
323 + }
324 +
325 + @Override
326 + public String toString() {
327 + IpAddress ipaddr = this.getIpAddress();
328 + String out = "PIM Neighbors: ";
329 + if (ipaddr != null) {
330 + out += "IP: " + ipaddr.toString();
331 + } else {
332 + out += "IP: *Null*";
333 + }
334 + out += "\tPR: " + String.valueOf(this.priority) + "\n";
335 + return out;
336 + }
337 +
338 +}
339 +
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.pim.impl;
17 +
18 +import org.jboss.netty.util.Timeout;
19 +import org.jboss.netty.util.TimerTask;
20 +import org.onosproject.incubator.net.config.basics.ConfigException;
21 +import org.onosproject.incubator.net.config.basics.InterfaceConfig;
22 +import org.onosproject.incubator.net.intf.Interface;
23 +import org.onosproject.incubator.net.intf.InterfaceService;
24 +import org.onosproject.net.ConnectPoint;
25 +
26 +import java.util.Collection;
27 +import java.util.HashMap;
28 +import java.util.Map;
29 +import java.util.Set;
30 +import java.util.concurrent.TimeUnit;
31 +
32 +import org.onosproject.net.config.NetworkConfigEvent;
33 +import org.onosproject.net.config.NetworkConfigListener;
34 +import org.onosproject.net.config.NetworkConfigService;
35 +import org.slf4j.Logger;
36 +import org.slf4j.LoggerFactory;
37 +
38 +/**
39 + * PIMInterfaces is a collection of all neighbors we have received
40 + * PIM hello messages from. The main structure is a HashMap indexed
41 + * by ConnectPoint with another HashMap indexed on the PIM neighbors
42 + * IPAddress, it contains all PIM neighbors attached on that ConnectPoint.
43 + */
44 +public final class PIMInterfaces {
45 +
46 + private Logger log = LoggerFactory.getLogger("PIMInterfaces");
47 +
48 + private static PIMInterfaces instance = null;
49 +
50 + // Used to listen to network configuration changes
51 + private NetworkConfigService configService;
52 +
53 + // Used to access IP Interface definitions for our segment
54 + private InterfaceService interfaceService;
55 +
56 + // Internal class used to listen for network configuration changes
57 + private InternalConfigListener configListener = new InternalConfigListener();
58 +
59 + // This is the global container for all PIM Interfaces indexed by ConnectPoints.
60 + private Map<ConnectPoint, PIMInterface> interfaces = new HashMap<>();
61 +
62 + // Default hello message interval
63 + private int helloMessageInterval = 60;
64 +
65 + // Timer used to send hello messages on this interface
66 + private Timeout helloTimer;
67 +
68 + // Required by a utility class
69 + private PIMInterfaces() {}
70 +
71 + /**
72 + * Get the instance of PIMInterfaces. Create the instance if needed.
73 + *
74 + * @return PIMInterface instance
75 + */
76 + public static PIMInterfaces getInstance() {
77 + if (null == instance) {
78 + instance = new PIMInterfaces();
79 + }
80 + return instance;
81 + }
82 +
83 + // Initialize the services
84 + public void initialize(NetworkConfigService cs, InterfaceService is) {
85 + configService = cs;
86 + interfaceService = is;
87 +
88 + // Initialize interfaces if they already exist
89 + initInterfaces();
90 +
91 + // Listen for network config changes
92 + configService.addListener(configListener);
93 + }
94 +
95 + /**
96 + * Listener for network config events.
97 + */
98 + private class InternalConfigListener implements NetworkConfigListener {
99 +
100 + private void updateInterfaces(InterfaceConfig config) {
101 + Set<Interface> intfs;
102 + try {
103 + intfs = config.getInterfaces();
104 + } catch (ConfigException e) {
105 + log.error(e.toString());
106 + return;
107 + }
108 + for (Interface intf : intfs) {
109 + addInterface(intf);
110 + }
111 + }
112 +
113 + /**
114 + * Remove the PIMInterface represented by the ConnectPoint. If the
115 + * PIMInterface does not exist this function is a no-op.
116 + *
117 + * @param cp The connectPoint representing the PIMInterface to be removed.
118 + */
119 + private void removeInterface(ConnectPoint cp) {
120 + removeInterface(cp);
121 + }
122 +
123 + @Override
124 + public void event(NetworkConfigEvent event) {
125 + switch (event.type()) {
126 + case CONFIG_ADDED:
127 + case CONFIG_UPDATED:
128 + log.debug("Config updated: " + event.toString() + "\n");
129 + if (event.configClass() == InterfaceConfig.class) {
130 + InterfaceConfig config =
131 + configService.getConfig((ConnectPoint) event.subject(), InterfaceConfig.class);
132 + updateInterfaces(config);
133 + }
134 + break;
135 + case CONFIG_REMOVED:
136 + if (event.configClass() == InterfaceConfig.class) {
137 + removeInterface((ConnectPoint) event.subject());
138 + }
139 + break;
140 + case CONFIG_REGISTERED:
141 + case CONFIG_UNREGISTERED:
142 + default:
143 + break;
144 + }
145 + }
146 + }
147 +
148 + // Configure interfaces if they already exist.
149 + private void initInterfaces() {
150 + Set<Interface> intfs = interfaceService.getInterfaces();
151 + for (Interface intf : intfs) {
152 + log.debug("Adding interface: " + intf.toString() + "\n");
153 + addInterface(intf);
154 + }
155 + }
156 +
157 + /**
158 + * Create a PIM Interface and add to our interfaces list.
159 + *
160 + * @param intf the interface to add
161 + * @return the PIMInterface
162 + */
163 + public PIMInterface addInterface(Interface intf) {
164 + PIMInterface pif = new PIMInterface(intf);
165 + interfaces.put(intf.connectPoint(), pif);
166 +
167 + // If we have added our first interface start the hello timer.
168 + if (interfaces.size() == 1) {
169 + startHelloTimer();
170 + }
171 +
172 + // Return this interface
173 + return pif;
174 + }
175 +
176 + /**
177 + * Remove the PIMInterface from the given ConnectPoint.
178 + *
179 + * @param cp the ConnectPoint indexing the PIMInterface to be removed.
180 + */
181 + public void removeInterface(ConnectPoint cp) {
182 + if (interfaces.containsKey(cp)) {
183 + interfaces.remove(cp);
184 + }
185 +
186 + if (interfaces.size() == 0) {
187 + PIMTimer.stop();
188 + }
189 + }
190 +
191 + /**
192 + * Return a collection of PIMInterfaces for use by the PIM Interface codec.
193 + *
194 + * @return the collection of PIMInterfaces
195 + */
196 + public Collection<PIMInterface> getInterfaces() {
197 + return interfaces.values();
198 + }
199 +
200 + /**
201 + * Get the PIM Interface indexed by the given ConnectPoint.
202 + *
203 + * @param cp the connect point
204 + * @return the PIMInterface if it exists, NULL if not
205 + */
206 + public PIMInterface getInterface(ConnectPoint cp) {
207 + return interfaces.get(cp);
208 + }
209 +
210 + /**
211 + * Return a string of PIMInterfaces for the cli command.
212 + *
213 + * @return a string representing PIM interfaces
214 + */
215 + public String printInterfaces() {
216 + String str = "";
217 + for (PIMInterface pi : interfaces.values()) {
218 + str += pi.toString();
219 + }
220 + return str;
221 + }
222 +
223 + /* ---------------------------------- PIM Hello Timer ----------------------------------- */
224 +
225 + /**
226 + * Start a new hello timer for this interface.
227 + */
228 + private void startHelloTimer() {
229 + helloTimer = PIMTimer.getTimer().newTimeout(
230 + new HelloTimer(),
231 + helloMessageInterval,
232 + TimeUnit.SECONDS);
233 +
234 + log.debug("Started Hello Timer");
235 + }
236 +
237 + /**
238 + * This inner class handles transmitting a PIM hello message on this ConnectPoint.
239 + */
240 + private final class HelloTimer implements TimerTask {
241 +
242 + HelloTimer() {
243 + }
244 +
245 + @Override
246 + public void run(Timeout timeout) throws Exception {
247 +
248 + log.debug("Running Hello Timer\n");
249 + // Technically we should not send all hello's in synch..
250 + for (PIMInterface pi : interfaces.values()) {
251 + pi.sendHello();
252 + }
253 +
254 + // restart the hello timer
255 + if (interfaces.size() > 0) {
256 + startHelloTimer();
257 + }
258 + }
259 + }
260 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -19,16 +19,15 @@ import com.fasterxml.jackson.databind.node.ArrayNode; ...@@ -19,16 +19,15 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
19 import com.fasterxml.jackson.databind.node.ObjectNode; 19 import com.fasterxml.jackson.databind.node.ObjectNode;
20 import org.onosproject.codec.CodecContext; 20 import org.onosproject.codec.CodecContext;
21 import org.onosproject.codec.JsonCodec; 21 import org.onosproject.codec.JsonCodec;
22 -import org.onosproject.net.ConnectPoint;
23 22
24 -import java.util.HashMap; 23 +import java.util.Collection;
25 24
26 import static com.google.common.base.Preconditions.checkNotNull; 25 import static com.google.common.base.Preconditions.checkNotNull;
27 26
28 /** 27 /**
29 * PIM neighbors Codec. 28 * PIM neighbors Codec.
30 */ 29 */
31 -public class PIMNeighborsCodec extends JsonCodec<HashMap<ConnectPoint, PIMNeighbors>> { 30 +public class PIMInterfacesCodec extends JsonCodec<Collection<PIMInterface>> {
32 // JSON field names 31 // JSON field names
33 //Return Name 32 //Return Name
34 private static final String CPNBRLIST = "connect_point_list"; 33 private static final String CPNBRLIST = "connect_point_list";
...@@ -53,22 +52,22 @@ public class PIMNeighborsCodec extends JsonCodec<HashMap<ConnectPoint, PIMNeighb ...@@ -53,22 +52,22 @@ public class PIMNeighborsCodec extends JsonCodec<HashMap<ConnectPoint, PIMNeighb
53 * @return Encoded neighbors used by CLI and REST 52 * @return Encoded neighbors used by CLI and REST
54 */ 53 */
55 @Override 54 @Override
56 - public ObjectNode encode(HashMap<ConnectPoint, PIMNeighbors> cpn, CodecContext context) { 55 + public ObjectNode encode(Collection<PIMInterface> cpn, CodecContext context) {
57 checkNotNull(cpn, "Pim Neighbors cannot be null"); 56 checkNotNull(cpn, "Pim Neighbors cannot be null");
58 57
59 ObjectNode pimNbrJsonCodec = context.mapper().createObjectNode(); 58 ObjectNode pimNbrJsonCodec = context.mapper().createObjectNode();
60 ArrayNode cpnList = context.mapper().createArrayNode(); 59 ArrayNode cpnList = context.mapper().createArrayNode();
61 60
62 - for (PIMNeighbors pn: cpn.values()) { 61 + for (PIMInterface pn: cpn) {
63 // get the PimNeighbors Obj, contains Neighbors list 62 // get the PimNeighbors Obj, contains Neighbors list
64 // create the json object for a single Entry in the Neighbors list 63 // create the json object for a single Entry in the Neighbors list
65 ObjectNode cp = context.mapper().createObjectNode(); 64 ObjectNode cp = context.mapper().createObjectNode();
66 - cp.put(IP, pn.getOurIpAddress().toString()); 65 + cp.put(IP, pn.getIpAddress().toString());
67 - cp.put(PRIORITY, String.valueOf(pn.getOurPriority())); 66 + cp.put(PRIORITY, String.valueOf(pn.getPriority()));
68 67
69 // create the array for the neighbors list 68 // create the array for the neighbors list
70 ArrayNode nbrsList = context.mapper().createArrayNode(); 69 ArrayNode nbrsList = context.mapper().createArrayNode();
71 - for (PIMNeighbor nbr : pn.getOurNeighborsList().values()) { 70 + for (PIMNeighbor nbr : pn.getNeighbors()) {
72 nbrsList.add(neighbor(nbr, context)); 71 nbrsList.add(neighbor(nbr, context));
73 } 72 }
74 // adds pim neighbor to list 73 // adds pim neighbor to list
......
...@@ -60,22 +60,20 @@ public class PIMNeighbor { ...@@ -60,22 +60,20 @@ public class PIMNeighbor {
60 // Timeout for this neighbor 60 // Timeout for this neighbor
61 private volatile Timeout timeout; 61 private volatile Timeout timeout;
62 62
63 - private boolean reelect = false;
64 -
65 // A back pointer the neighbors list this neighbor belongs to. 63 // A back pointer the neighbors list this neighbor belongs to.
66 - private PIMNeighbors neighbors; 64 + private PIMInterface pimInterface;
67 65
68 /** 66 /**
69 * Construct this neighbor from the address and connect point. 67 * Construct this neighbor from the address and connect point.
70 * 68 *
71 * @param ipaddr IP Address of neighbor 69 * @param ipaddr IP Address of neighbor
72 * @param macaddr MAC Address of the neighbor 70 * @param macaddr MAC Address of the neighbor
73 - * @param cp The ConnectPoint of this neighbor 71 + * @param pimInterface The PIMInterface of this neighbor
74 */ 72 */
75 - public PIMNeighbor(IpAddress ipaddr, MacAddress macaddr, ConnectPoint cp) { 73 + public PIMNeighbor(IpAddress ipaddr, MacAddress macaddr, PIMInterface pimInterface) {
76 this.macAddress = macaddr; 74 this.macAddress = macaddr;
77 this.primaryAddr = ipaddr; 75 this.primaryAddr = ipaddr;
78 - this.connectPoint = cp; 76 + this.pimInterface = pimInterface;
79 this.resetTimeout(); 77 this.resetTimeout();
80 } 78 }
81 79
...@@ -174,30 +172,12 @@ public class PIMNeighbor { ...@@ -174,30 +172,12 @@ public class PIMNeighbor {
174 * 172 *
175 * @return the ConnectPoint 173 * @return the ConnectPoint
176 */ 174 */
177 - public ConnectPoint getConnectPoint() { 175 + public PIMInterface getPimInterface() {
178 - return connectPoint; 176 + return pimInterface;
179 - }
180 -
181 - /**
182 - * Set the ConnectPoint this router is connected to.
183 - *
184 - * @param connectPoint the ConnectPoint this router is connected to.
185 - */
186 - public void setConnectPoint(ConnectPoint connectPoint) {
187 - this.connectPoint = connectPoint;
188 } 177 }
189 178
190 /** 179 /**
191 - * Set a back pointer to the neighbors list this neighbor is a member of. 180 + * We have received a fresh hello from this neighbor, now we need to process it.
192 - *
193 - * @param neighbors the neighbor list this neighbor belongs to
194 - */
195 - public void setNeighbors(PIMNeighbors neighbors) {
196 - this.neighbors = neighbors;
197 - }
198 -
199 - /**
200 - * We have received a fresh hello from a neighbor, now we need to process it.
201 * Depending on the values received in the the hello options may force a 181 * Depending on the values received in the the hello options may force a
202 * re-election process. 182 * re-election process.
203 * 183 *
...@@ -208,17 +188,19 @@ public class PIMNeighbor { ...@@ -208,17 +188,19 @@ public class PIMNeighbor {
208 public void refresh(PIMHello hello) { 188 public void refresh(PIMHello hello) {
209 checkNotNull(hello); 189 checkNotNull(hello);
210 190
191 + boolean reelect = false;
211 for (PIMHelloOption opt : hello.getOptions().values()) { 192 for (PIMHelloOption opt : hello.getOptions().values()) {
212 193
213 int len = opt.getOptLength(); 194 int len = opt.getOptLength();
214 - byte [] value = new byte[len]; 195 + ByteBuffer bb = ByteBuffer.wrap(opt.getValue());
215 - ByteBuffer bb = ByteBuffer.wrap(value);
216 196
217 switch (opt.getOptType()) { 197 switch (opt.getOptType()) {
218 case PIMHelloOption.OPT_GENID: 198 case PIMHelloOption.OPT_GENID:
219 int newid = bb.getInt(); 199 int newid = bb.getInt();
220 if (this.genId != newid) { 200 if (this.genId != newid) {
221 - // TODO: we have a newly rebooted neighbor. Send them our joins. 201 +
202 + // We have a newly rebooted neighbor, this is where we would
203 + // send them our joins.
222 this.genId = newid; 204 this.genId = newid;
223 } 205 }
224 break; 206 break;
...@@ -228,7 +210,7 @@ public class PIMNeighbor { ...@@ -228,7 +210,7 @@ public class PIMNeighbor {
228 if (this.priority != newpri) { 210 if (this.priority != newpri) {
229 211
230 // The priorities have changed. We may need to re-elect a new DR? 212 // The priorities have changed. We may need to re-elect a new DR?
231 - if (this.isDr || this.neighbors.getDesignatedRouter().getPriority() < priority) { 213 + if (this.isDr || pimInterface.getDesignatedRouter().getPriority() < priority) {
232 reelect = true; 214 reelect = true;
233 } 215 }
234 this.priority = newpri; 216 this.priority = newpri;
...@@ -242,7 +224,6 @@ public class PIMNeighbor { ...@@ -242,7 +224,6 @@ public class PIMNeighbor {
242 if (holdtime == 0) { 224 if (holdtime == 0) {
243 // We have a neighbor going down. We can remove all joins 225 // We have a neighbor going down. We can remove all joins
244 // we have learned from them. 226 // we have learned from them.
245 - // TODO: What else do we need to do when a neighbor goes down?
246 227
247 log.debug("PIM Neighbor has timed out: {}", this.primaryAddr.toString()); 228 log.debug("PIM Neighbor has timed out: {}", this.primaryAddr.toString());
248 return; 229 return;
...@@ -261,7 +242,7 @@ public class PIMNeighbor { ...@@ -261,7 +242,7 @@ public class PIMNeighbor {
261 } 242 }
262 243
263 if (reelect) { 244 if (reelect) {
264 - this.neighbors.electDR(this); 245 + pimInterface.electDR(this);
265 } 246 }
266 247
267 // Reset the next timeout timer 248 // Reset the next timeout timer
...@@ -307,9 +288,8 @@ public class PIMNeighbor { ...@@ -307,9 +288,8 @@ public class PIMNeighbor {
307 @Override 288 @Override
308 public void run(Timeout timeout) throws Exception { 289 public void run(Timeout timeout) throws Exception {
309 290
310 - // TODO: log.debug; 291 + log.debug("PIM Neighbor {} has timed out: ", nbr.toString());
311 - PIMNeighbors neighbors = nbr.neighbors; 292 + nbr.pimInterface.removeNeighbor(nbr);
312 - neighbors.removeNeighbor(nbr.getPrimaryAddr());
313 } 293 }
314 } 294 }
315 295
......
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.pim.impl;
17 +
18 +import org.onlab.packet.Ethernet;
19 +import org.onlab.packet.IPv4;
20 +import org.onlab.packet.Ip4Address;
21 +import org.onlab.packet.IpAddress;
22 +import org.onlab.packet.IpPrefix;
23 +import org.onlab.packet.MacAddress;
24 +import org.onlab.packet.PIM;
25 +import org.onlab.packet.VlanId;
26 +import org.onosproject.core.ApplicationId;
27 +import org.onosproject.incubator.net.intf.Interface;
28 +import org.onosproject.net.ConnectPoint;
29 +import org.onosproject.net.flow.DefaultTrafficSelector;
30 +import org.onosproject.net.flow.DefaultTrafficTreatment;
31 +import org.onosproject.net.flow.TrafficSelector;
32 +import org.onosproject.net.flow.TrafficTreatment;
33 +import org.onosproject.net.packet.DefaultOutboundPacket;
34 +import org.onosproject.net.packet.InboundPacket;
35 +import org.onosproject.net.packet.OutboundPacket;
36 +import org.onosproject.net.packet.PacketContext;
37 +import org.onosproject.net.packet.PacketPriority;
38 +import org.onosproject.net.packet.PacketProcessor;
39 +import org.onosproject.net.packet.PacketService;
40 +import org.slf4j.Logger;
41 +
42 +import java.nio.ByteBuffer;
43 +
44 +import static com.google.common.base.Preconditions.checkNotNull;
45 +import static org.slf4j.LoggerFactory.getLogger;
46 +
47 +/**
48 + * Handing Incoming and outgoing PIM packets.
49 + */
50 +public final class PIMPacketHandler {
51 + private final Logger log = getLogger(getClass());
52 +
53 + private static PIMPacketHandler instance = null;
54 +
55 + private PacketService packetService;
56 + private PIMPacketProcessor processor = new PIMPacketProcessor();
57 + private MacAddress pimDestinationMac = MacAddress.valueOf("01:00:5E:00:00:0d");
58 +
59 + // Utility class
60 + private PIMPacketHandler() {}
61 +
62 + public static PIMPacketHandler getInstance() {
63 + if (null == instance) {
64 + instance = new PIMPacketHandler();
65 + }
66 + return instance;
67 + }
68 +
69 + /**
70 + * Initialize the packet handling service.
71 + *
72 + * @param ps the packetService
73 + * @param appId our application ID
74 + */
75 + public void initialize(PacketService ps, ApplicationId appId) {
76 + packetService = ps;
77 +
78 + // Build a traffic selector for all multicast traffic
79 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
80 + selector.matchEthType(Ethernet.TYPE_IPV4);
81 + selector.matchIPProtocol(IPv4.PROTOCOL_PIM);
82 + packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
83 +
84 + packetService.addProcessor(processor, PacketProcessor.director(1));
85 + }
86 +
87 + /**
88 + * Shutdown the packet handling service.
89 + */
90 + public void stop() {
91 + packetService.removeProcessor(processor);
92 + processor = null;
93 + }
94 +
95 + /**
96 + * Packet processor responsible for handling IGMP packets.
97 + */
98 + public class PIMPacketProcessor implements PacketProcessor {
99 + private final Logger log = getLogger(getClass());
100 +
101 + @Override
102 + public void process(PacketContext context) {
103 + // Stop processing if the packet has been handled, since we
104 + // can't do any more to it.
105 + if (context.isHandled()) {
106 + return;
107 + }
108 +
109 + InboundPacket pkt = context.inPacket();
110 + if (pkt == null) {
111 + return;
112 + }
113 +
114 + Ethernet ethPkt = pkt.parsed();
115 + if (ethPkt == null) {
116 + return;
117 + }
118 +
119 + /*
120 + * IPv6 MLD packets are handled by ICMP6. We'll only deal
121 + * with IPv4.
122 + */
123 + if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) {
124 + return;
125 + }
126 +
127 + IPv4 ip = (IPv4) ethPkt.getPayload();
128 + IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress());
129 + IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress());
130 + log.debug("Packet (" + saddr.toString() + ", " + gaddr.toString() +
131 + "\tingress port: " + context.inPacket().receivedFrom().toString());
132 +
133 + if (ip.getProtocol() != IPv4.PROTOCOL_PIM) {
134 + log.debug("PIM Picked up a non PIM packet: IP protocol: " + ip.getProtocol());
135 + return;
136 + }
137 +
138 + // TODO: check incoming to be PIM.PIM_ADDRESS or "Our" address.
139 + IpPrefix spfx = IpPrefix.valueOf(saddr, 32);
140 + IpPrefix gpfx = IpPrefix.valueOf(gaddr, 32);
141 +
142 + PIM pim = (PIM) ip.getPayload();
143 + switch (pim.getPimMsgType()) {
144 +
145 + case PIM.TYPE_HELLO:
146 + processHello(ethPkt, context.inPacket().receivedFrom());
147 + break;
148 +
149 + case PIM.TYPE_JOIN_PRUNE_REQUEST:
150 + // Create the function
151 + break;
152 +
153 + case PIM.TYPE_ASSERT:
154 + case PIM.TYPE_BOOTSTRAP:
155 + case PIM.TYPE_CANDIDATE_RP_ADV:
156 + case PIM.TYPE_GRAFT:
157 + case PIM.TYPE_GRAFT_ACK:
158 + case PIM.TYPE_REGISTER:
159 + case PIM.TYPE_REGISTER_STOP:
160 + log.debug("Unsupported PIM message type: " + pim.getPimMsgType());
161 + break;
162 +
163 + default:
164 + log.debug("Unkown PIM message type: " + pim.getPimMsgType());
165 + break;
166 + }
167 + }
168 +
169 + /**
170 + * Process incoming hello message, we will need the Macaddress and IP address of the sender.
171 + *
172 + * @param ethPkt the ethernet header
173 + * @param receivedFrom the connect point we recieved this message from
174 + */
175 + private void processHello(Ethernet ethPkt, ConnectPoint receivedFrom) {
176 + checkNotNull(ethPkt);
177 + checkNotNull(receivedFrom);
178 +
179 + // It is a problem if we don't have the
180 + PIMInterfaces pintfs = PIMInterfaces.getInstance();
181 + PIMInterface intf = pintfs.getInterface(receivedFrom);
182 + if (intf == null) {
183 + log.error("We received a PIM message on an interface we were not supposed to");
184 + return;
185 + }
186 + intf.processHello(ethPkt, receivedFrom);
187 + }
188 + }
189 +
190 + // Create an ethernet header and serialize then send
191 + public void sendPacket(PIM pim, PIMInterface pimIntf) {
192 +
193 + Interface theInterface = pimIntf.getInterface();
194 +
195 + // Create the ethernet packet
196 + Ethernet eth = new Ethernet();
197 + eth.setDestinationMACAddress(pimDestinationMac);
198 + eth.setSourceMACAddress(theInterface.mac());
199 + eth.setEtherType(Ethernet.TYPE_IPV4);
200 + if (theInterface.vlan() != VlanId.NONE) {
201 + eth.setVlanID(theInterface.vlan().toShort());
202 + }
203 +
204 + // Create the IP Packet
205 + IPv4 ip = new IPv4();
206 + ip.setVersion((byte) 4);
207 + ip.setTtl((byte) 20);
208 + ip.setProtocol(IPv4.PROTOCOL_PIM);
209 + ip.setChecksum((short) 0);
210 + ip.setSourceAddress(checkNotNull(pimIntf.getIpAddress()).getIp4Address().toInt());
211 + ip.setDestinationAddress(PIM.PIM_ADDRESS.getIp4Address().toInt());
212 + eth.setPayload(ip);
213 + ip.setParent(eth);
214 +
215 + // Now set pim
216 + ip.setPayload(pim);
217 + pim.setParent(ip);
218 +
219 + ConnectPoint cp = theInterface.connectPoint();
220 + checkNotNull(cp);
221 +
222 + TrafficTreatment treat = DefaultTrafficTreatment.builder().setOutput(cp.port()).build();
223 + ByteBuffer bb = ByteBuffer.wrap(eth.serialize());
224 + OutboundPacket packet = new DefaultOutboundPacket(cp.deviceId(), treat, bb);
225 + checkNotNull(packet);
226 +
227 + packetService.emit(packet);
228 + }
229 +}
...@@ -17,6 +17,8 @@ package org.onosproject.pim.impl; ...@@ -17,6 +17,8 @@ package org.onosproject.pim.impl;
17 17
18 import org.jboss.netty.util.HashedWheelTimer; 18 import org.jboss.netty.util.HashedWheelTimer;
19 19
20 +import static com.google.common.base.Preconditions.checkNotNull;
21 +
20 /** 22 /**
21 * PIM Timer used for PIM Neighbors. 23 * PIM Timer used for PIM Neighbors.
22 */ 24 */
...@@ -50,4 +52,21 @@ public final class PIMTimer { ...@@ -50,4 +52,21 @@ public final class PIMTimer {
50 PIMTimer.timer = hwTimer; 52 PIMTimer.timer = hwTimer;
51 } 53 }
52 } 54 }
55 +
56 + public static void start() {
57 + if (PIMTimer.timer == null) {
58 + getTimer();
59 + }
60 + checkNotNull(timer);
61 + timer.start();
62 + }
63 +
64 + public static void stop() {
65 + if (PIMTimer.timer == null) {
66 + // No need to stop
67 + return;
68 + }
69 + checkNotNull(timer);
70 + timer.stop();
71 + }
53 } 72 }
......