Committed by
Gerrit Code Review
Blew away old version of PIM to restructure. And:
1) Added packetService to register for PIM packets. 2) Added PIMPacketHandler to process PIM packets. 3) Added NetworkConfig Listener 4) Added PIMInterfaceService / PIMInterfaceManager 5) Added Process incoming hello packets to PIMInterfaceManager 6) Code Review inspired changes Change-Id: I753880c954b9a6a91544903b613305ff9aa78cd0
Showing
12 changed files
with
439 additions
and
1060 deletions
1 | -/* | ||
2 | - * Copyright 2014-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.cli; | ||
17 | - | ||
18 | -import com.fasterxml.jackson.databind.JsonNode; | ||
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.PIMInterfaces; | ||
23 | -import org.onosproject.pim.impl.PIMInterfacesCodec; | ||
24 | - | ||
25 | -import java.util.Collection; | ||
26 | - | ||
27 | -@Command(scope = "onos", name = "pim-interfaces", description = "Displays the pim interfaces") | ||
28 | -public class PIMShowCommand extends AbstractShellCommand { | ||
29 | - | ||
30 | - // prints either the json or cli version of the hash map connect point | ||
31 | - // neighbors from the PIMInterfaces class. | ||
32 | - @Override | ||
33 | - protected void execute() { | ||
34 | - // grab connect point neighbors hash map to send in to json encoder. | ||
35 | - Collection<PIMInterface> pimIntfs = PIMInterfaces.getInstance().getInterfaces(); | ||
36 | - if (outputJson()) { | ||
37 | - print("%s", json(pimIntfs)); | ||
38 | - } else { | ||
39 | - print(PIMInterfaces.getInstance().printInterfaces()); | ||
40 | - } | ||
41 | - } | ||
42 | - | ||
43 | - private JsonNode json(Collection<PIMInterface> pimIntfs) { | ||
44 | - return new PIMInterfacesCodec().encode(pimIntfs, this); | ||
45 | - } | ||
46 | - | ||
47 | -} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
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.apache.felix.scr.annotations.Activate; | ||
19 | +import org.apache.felix.scr.annotations.Component; | ||
20 | +import org.apache.felix.scr.annotations.Deactivate; | ||
21 | +import org.apache.felix.scr.annotations.Reference; | ||
22 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
23 | +import org.onlab.packet.Ethernet; | ||
24 | +import org.onlab.packet.IPv4; | ||
25 | +import org.onosproject.core.ApplicationId; | ||
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; | ||
36 | +import org.onosproject.net.flow.TrafficSelector; | ||
37 | +import org.onosproject.net.mcast.MulticastRouteService; | ||
38 | +import org.onosproject.net.packet.InboundPacket; | ||
39 | +import org.onosproject.net.packet.PacketContext; | ||
40 | +import org.onosproject.net.packet.PacketProcessor; | ||
41 | +import org.onosproject.net.packet.PacketService; | ||
42 | +import org.slf4j.Logger; | ||
43 | + | ||
44 | +import java.util.Set; | ||
45 | + | ||
46 | +import static org.slf4j.LoggerFactory.getLogger; | ||
47 | + | ||
48 | +/** | ||
49 | + * The main PIM controller class. | ||
50 | + */ | ||
51 | +@Component(immediate = true) | ||
52 | +public class PIMApplication { | ||
53 | + private final Logger log = getLogger(getClass()); | ||
54 | + | ||
55 | + // Used to get the appId | ||
56 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
57 | + protected CoreService coreService; | ||
58 | + | ||
59 | + // Our application ID | ||
60 | + private static ApplicationId appId; | ||
61 | + | ||
62 | + // Register to receive PIM packets, used to send packets as well | ||
63 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
64 | + protected PacketService packetService; | ||
65 | + | ||
66 | + // Use the MulticastRouteService to manage incoming PIM Join/Prune state as well as | ||
67 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
68 | + protected MulticastRouteService ms; | ||
69 | + | ||
70 | + // Create an instance of the PIM packet handler | ||
71 | + protected PIMPacketHandler pimPacketHandler; | ||
72 | + | ||
73 | + // Get the network configuration updates | ||
74 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
75 | + protected NetworkConfigService configService; | ||
76 | + | ||
77 | + // Access defined network (IP) interfaces | ||
78 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
79 | + protected InterfaceService interfaceService; | ||
80 | + | ||
81 | + // Internal class used to listen for network configuration changes | ||
82 | + private InternalConfigListener configListener = new InternalConfigListener(); | ||
83 | + | ||
84 | + // Provide interfaces to the pimInterface manager as a result of Netconfig updates. | ||
85 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
86 | + protected PIMInterfaceService pimInterfaceManager; | ||
87 | + | ||
88 | + /** | ||
89 | + * Activate the PIM component. | ||
90 | + */ | ||
91 | + @Activate | ||
92 | + public void activate() { | ||
93 | + | ||
94 | + // Get our application ID | ||
95 | + appId = coreService.registerApplication("org.onosproject.pim"); | ||
96 | + | ||
97 | + // Build the traffic selector for PIM packets | ||
98 | + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | ||
99 | + selector.matchEthType(Ethernet.TYPE_IPV4); | ||
100 | + selector.matchIPProtocol(IPv4.PROTOCOL_PIM); | ||
101 | + | ||
102 | + // Use the traffic selector to tell the packet service which packets we want. | ||
103 | + // PIMPacketService is an inner class defined below | ||
104 | + PIMPacketProcessor processor = new PIMPacketProcessor(); | ||
105 | + packetService.addProcessor(processor, PacketProcessor.director(5)); | ||
106 | + | ||
107 | + // Register for notifications from the Network config & Interface services. | ||
108 | + // We'll use these services to represent "PIMInterfaces" | ||
109 | + | ||
110 | + // Get a copy of the PIM Packet Handler | ||
111 | + pimPacketHandler = new PIMPacketHandler(); | ||
112 | + | ||
113 | + // Listen for network configuration changes | ||
114 | + configService.addListener(configListener); | ||
115 | + | ||
116 | + log.info("Started"); | ||
117 | + } | ||
118 | + | ||
119 | + /** | ||
120 | + * Deactivate the PIM component. | ||
121 | + */ | ||
122 | + @Deactivate | ||
123 | + public void deactivate() { | ||
124 | + log.info("Stopped"); | ||
125 | + } | ||
126 | + | ||
127 | + /** | ||
128 | + * The class that will receive PIM packets, sanitize them, determine the PIMInterface | ||
129 | + * they arrived on, then forward them on to be processed by the appropriate entity. | ||
130 | + */ | ||
131 | + public class PIMPacketProcessor implements PacketProcessor { | ||
132 | + private final Logger log = getLogger(getClass()); | ||
133 | + | ||
134 | + @Override | ||
135 | + public void process(PacketContext context) { | ||
136 | + | ||
137 | + // return if this packet has already been handled | ||
138 | + if (context.isHandled()) { | ||
139 | + return; | ||
140 | + } | ||
141 | + | ||
142 | + // get the inbound packet | ||
143 | + InboundPacket pkt = context.inPacket(); | ||
144 | + if (pkt == null) { | ||
145 | + // problem getting the inbound pkt. Log it debug to avoid spamming log file | ||
146 | + log.debug("Could not retrieve packet from context"); | ||
147 | + return; | ||
148 | + } | ||
149 | + | ||
150 | + // Get the ethernet header | ||
151 | + Ethernet eth = pkt.parsed(); | ||
152 | + if (eth == null) { | ||
153 | + // problem getting the ethernet pkt. Log it debug to avoid spamming log file | ||
154 | + log.debug("Could not retrieve ethnernet packet from the parsed packet"); | ||
155 | + return; | ||
156 | + } | ||
157 | + | ||
158 | + // Get the PIM Interface the packet was received on. | ||
159 | + PIMInterface pimi = pimInterfaceManager.getPIMInterface(pkt.receivedFrom()); | ||
160 | + if (pimi == null) { | ||
161 | + log.debug("We received PIM packet from a non PIM interface: " + pkt.receivedFrom().toString()); | ||
162 | + return; | ||
163 | + } | ||
164 | + | ||
165 | + /* | ||
166 | + * Pass the packet processing off to the PIMInterface for processing. | ||
167 | + * | ||
168 | + * TODO: Is it possible that PIM interface processing should move to the | ||
169 | + * PIMInterfaceManager directly? | ||
170 | + */ | ||
171 | + PIMPacketHandler ph = new PIMPacketHandler(); | ||
172 | + ph.processPacket(eth, pimi); | ||
173 | + } | ||
174 | + } | ||
175 | + | ||
176 | + /* | ||
177 | + * This class receives all events from the network config services, then hands the | ||
178 | + * event off to the PIMInterfaceManager for proper handling. | ||
179 | + * | ||
180 | + * TODO: should this move to PIMInterfaceManager? | ||
181 | + */ | ||
182 | + private class InternalConfigListener implements NetworkConfigListener { | ||
183 | + | ||
184 | + @Override | ||
185 | + public void event(NetworkConfigEvent event) { | ||
186 | + | ||
187 | + log.debug(event.toString()); | ||
188 | + switch (event.type()) { | ||
189 | + case CONFIG_ADDED: | ||
190 | + case CONFIG_UPDATED: | ||
191 | + | ||
192 | + if (event.configClass() == InterfaceConfig.class) { | ||
193 | + InterfaceConfig config = configService.getConfig( | ||
194 | + (ConnectPoint) event.subject(), | ||
195 | + InterfaceConfig.class); | ||
196 | + | ||
197 | + log.debug("Got a network configuration event"); | ||
198 | + | ||
199 | + // Walk the interfaces and feed them to the PIMInterfaceManager | ||
200 | + Set<Interface> intfs; | ||
201 | + try { | ||
202 | + intfs = config.getInterfaces(); | ||
203 | + for (Interface intf : intfs) { | ||
204 | + pimInterfaceManager.updateInterface(intf); | ||
205 | + } | ||
206 | + } catch (ConfigException e) { | ||
207 | + log.error(e.toString()); | ||
208 | + return; | ||
209 | + } | ||
210 | + } | ||
211 | + break; | ||
212 | + | ||
213 | + case CONFIG_REMOVED: | ||
214 | + if (event.configClass() == InterfaceConfig.class) { | ||
215 | + ConnectPoint cp = (ConnectPoint) event.subject(); | ||
216 | + //assertNotNull(cp); | ||
217 | + pimInterfaceManager.deleteInterface(cp); | ||
218 | + } | ||
219 | + break; | ||
220 | + | ||
221 | + case CONFIG_REGISTERED: | ||
222 | + case CONFIG_UNREGISTERED: | ||
223 | + default: | ||
224 | + log.debug("\tWe are not handling this event type"); | ||
225 | + break; | ||
226 | + } | ||
227 | + } | ||
228 | + } | ||
229 | +} |
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 static org.slf4j.LoggerFactory.getLogger; | ||
19 | - | ||
20 | -import org.apache.felix.scr.annotations.Activate; | ||
21 | -import org.apache.felix.scr.annotations.Component; | ||
22 | -import org.apache.felix.scr.annotations.Deactivate; | ||
23 | -import org.apache.felix.scr.annotations.Reference; | ||
24 | -import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
25 | -import org.onosproject.core.ApplicationId; | ||
26 | -import org.onosproject.core.CoreService; | ||
27 | -import org.onosproject.incubator.net.intf.InterfaceService; | ||
28 | -import org.onosproject.net.config.NetworkConfigService; | ||
29 | -import org.onosproject.net.packet.PacketService; | ||
30 | -import org.slf4j.Logger; | ||
31 | - | ||
32 | -/** | ||
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. | ||
36 | - */ | ||
37 | -@Component(immediate = true) | ||
38 | -public class PIMComponent { | ||
39 | - private final Logger log = getLogger(getClass()); | ||
40 | - | ||
41 | - // Register to receive PIM packets, used to send packets as well | ||
42 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
43 | - protected PacketService packetService; | ||
44 | - | ||
45 | - // Get the appId | ||
46 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
47 | - protected CoreService coreService; | ||
48 | - | ||
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 | - | ||
57 | - private static ApplicationId appId; | ||
58 | - | ||
59 | - private PIMInterfaces pimInterfaces; | ||
60 | - private PIMPacketHandler pimPacketHandler; | ||
61 | - | ||
62 | - @Activate | ||
63 | - public void activate() { | ||
64 | - appId = coreService.registerApplication("org.onosproject.pim"); | ||
65 | - | ||
66 | - // Initialize the Packet Handler class | ||
67 | - pimPacketHandler = PIMPacketHandler.getInstance(); | ||
68 | - pimPacketHandler.initialize(packetService, appId); | ||
69 | - | ||
70 | - // Initialize the Interface class | ||
71 | - pimInterfaces = PIMInterfaces.getInstance(); | ||
72 | - pimInterfaces.initialize(configService, interfaceService); | ||
73 | - | ||
74 | - log.info("Started"); | ||
75 | - } | ||
76 | - | ||
77 | - @Deactivate | ||
78 | - public void deactivate() { | ||
79 | - PIMPacketHandler.getInstance().stop(); | ||
80 | - log.info("Stopped"); | ||
81 | - } | ||
82 | -} |
This diff is collapsed. Click to expand it.
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 com.google.common.collect.Maps; | ||
19 | +import org.apache.felix.scr.annotations.Activate; | ||
20 | +import org.apache.felix.scr.annotations.Component; | ||
21 | +import org.apache.felix.scr.annotations.Deactivate; | ||
22 | +import org.apache.felix.scr.annotations.Reference; | ||
23 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
24 | +import org.apache.felix.scr.annotations.Service; | ||
25 | +import org.onosproject.incubator.net.intf.Interface; | ||
26 | +import org.onosproject.incubator.net.intf.InterfaceService; | ||
27 | +import org.onosproject.net.ConnectPoint; | ||
28 | +import org.onosproject.net.provider.ProviderId; | ||
29 | +import org.slf4j.Logger; | ||
30 | +import java.util.Map; | ||
31 | + | ||
32 | +import static org.slf4j.LoggerFactory.getLogger; | ||
33 | + | ||
34 | +/** | ||
35 | + * Manages PIMInterfaces. | ||
36 | + * | ||
37 | + * TODO: Do we need to add a ServiceListener? | ||
38 | + */ | ||
39 | +@Component(immediate = true) | ||
40 | +@Service | ||
41 | +public class PIMInterfaceManager implements PIMInterfaceService { | ||
42 | + | ||
43 | + private final Logger log = getLogger(getClass()); | ||
44 | + | ||
45 | + // Create ourselves a provider ID | ||
46 | + private static final ProviderId PID = new ProviderId("pim", "org.onosproject.pim"); | ||
47 | + | ||
48 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
49 | + protected InterfaceService interfaceService; | ||
50 | + | ||
51 | + // Store PIM Interfaces in a map key'd by ConnectPoint | ||
52 | + private final Map<ConnectPoint, PIMInterface> pimInterfaces = Maps.newConcurrentMap(); | ||
53 | + | ||
54 | + @Activate | ||
55 | + public void activate() { | ||
56 | + // Query the Interface service to see if Interfaces already exist. | ||
57 | + log.info("Started"); | ||
58 | + | ||
59 | + // Create PIM Interfaces for each of the existing ONOS Interfaces. | ||
60 | + for (Interface intf : interfaceService.getInterfaces()) { | ||
61 | + pimInterfaces.put(intf.connectPoint(), new PIMInterface(intf)); | ||
62 | + } | ||
63 | + } | ||
64 | + | ||
65 | + @Deactivate | ||
66 | + public void deactivate() { | ||
67 | + log.info("Stopped"); | ||
68 | + } | ||
69 | + | ||
70 | + /** | ||
71 | + * Update the ONOS Interface with the new Interface. If the PIMInterface does | ||
72 | + * not exist we'll create a new one and store it. | ||
73 | + * | ||
74 | + * @param intf ONOS Interface. | ||
75 | + */ | ||
76 | + @Override | ||
77 | + public void updateInterface(Interface intf) { | ||
78 | + ConnectPoint cp = intf.connectPoint(); | ||
79 | + | ||
80 | + log.debug("Updating Interface for " + intf.connectPoint().toString()); | ||
81 | + pimInterfaces.compute(cp, (k, v) -> (v == null) ? | ||
82 | + new PIMInterface(intf) : | ||
83 | + v.setInterface(intf)); | ||
84 | + } | ||
85 | + | ||
86 | + /** | ||
87 | + * Delete the PIM Interface to the corresponding ConnectPoint. | ||
88 | + * | ||
89 | + * @param cp The connect point associated with this interface we want to delete | ||
90 | + */ | ||
91 | + @Override | ||
92 | + public void deleteInterface(ConnectPoint cp) { | ||
93 | + | ||
94 | + PIMInterface pi = pimInterfaces.remove(cp); | ||
95 | + if (pi == null) { | ||
96 | + log.warn("We've been asked to remove an interface we3 don't have: " + cp.toString()); | ||
97 | + return; | ||
98 | + } | ||
99 | + } | ||
100 | + | ||
101 | + /** | ||
102 | + * Return the PIMInterface that corresponds to the given ConnectPoint. | ||
103 | + * | ||
104 | + * @param cp The ConnectPoint we want to get the PIMInterface for | ||
105 | + * @return The PIMInterface if it exists, NULL if it does not exist. | ||
106 | + */ | ||
107 | + @Override | ||
108 | + public PIMInterface getPIMInterface(ConnectPoint cp) { | ||
109 | + PIMInterface pi = pimInterfaces.getOrDefault(cp, null); | ||
110 | + if (pi == null) { | ||
111 | + log.warn("We have been asked for an Interface we don't have: " + cp.toString()); | ||
112 | + } | ||
113 | + return pi; | ||
114 | + } | ||
115 | +} |
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.onosproject.incubator.net.intf.Interface; | ||
19 | +import org.onosproject.net.ConnectPoint; | ||
20 | + | ||
21 | +/** | ||
22 | + * Define the PIMInterfaceService. PIM will use ONOS Interfaces to | ||
23 | + * define PIM Interfaces. The PIM Application signed up as a Netconfig | ||
24 | + * listener. | ||
25 | + * | ||
26 | + * TODO: Do we need a PIMInterfaceListenerService? Who sould listen to Interfaces changes? | ||
27 | + */ | ||
28 | +public interface PIMInterfaceService { | ||
29 | + | ||
30 | + /** | ||
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. | ||
47 | + * | ||
48 | + * @param cp The ConnectPoint we want to get the PIMInterface for. | ||
49 | + * @return the PIMInterface if it exists, NULL if it does not exist. | ||
50 | + */ | ||
51 | + public PIMInterface getPIMInterface(ConnectPoint cp); | ||
52 | +} |
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 | - PIMInterfaces.this.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 |
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 com.fasterxml.jackson.databind.node.ArrayNode; | ||
19 | -import com.fasterxml.jackson.databind.node.ObjectNode; | ||
20 | -import org.onosproject.codec.CodecContext; | ||
21 | -import org.onosproject.codec.JsonCodec; | ||
22 | - | ||
23 | -import java.util.Collection; | ||
24 | - | ||
25 | -import static com.google.common.base.Preconditions.checkNotNull; | ||
26 | - | ||
27 | -/** | ||
28 | - * PIM neighbors Codec. | ||
29 | - */ | ||
30 | -public class PIMInterfacesCodec extends JsonCodec<Collection<PIMInterface>> { | ||
31 | - // JSON field names | ||
32 | - //Return Name | ||
33 | - private static final String CPNBRLIST = "connect_point_list"; | ||
34 | - | ||
35 | - // PIM Neightbors Fields | ||
36 | - private static final String IP = "ip"; | ||
37 | - private static final String PRIORITY = "priority"; | ||
38 | - private static final String NBRLIST = "neighbor_list"; | ||
39 | - | ||
40 | - // PIM neighbor Files | ||
41 | - private static final String DR = "designated"; | ||
42 | - private static final String NBR_IP = "ip"; | ||
43 | - private static final String PR = "priority"; | ||
44 | - private static final String HOLDTIME = "hold_time"; | ||
45 | - | ||
46 | - /** | ||
47 | - * Encode the PIM Neighbors. | ||
48 | - * | ||
49 | - * @param cpn ConnectPoint neighbors | ||
50 | - * @param context encoding context | ||
51 | - * | ||
52 | - * @return Encoded neighbors used by CLI and REST | ||
53 | - */ | ||
54 | - @Override | ||
55 | - public ObjectNode encode(Collection<PIMInterface> cpn, CodecContext context) { | ||
56 | - checkNotNull(cpn, "Pim Neighbors cannot be null"); | ||
57 | - | ||
58 | - ObjectNode pimNbrJsonCodec = context.mapper().createObjectNode(); | ||
59 | - ArrayNode cpnList = context.mapper().createArrayNode(); | ||
60 | - | ||
61 | - for (PIMInterface pn: cpn) { | ||
62 | - // get the PimNeighbors Obj, contains Neighbors list | ||
63 | - // create the json object for a single Entry in the Neighbors list | ||
64 | - ObjectNode cp = context.mapper().createObjectNode(); | ||
65 | - cp.put(IP, pn.getIpAddress().toString()); | ||
66 | - cp.put(PRIORITY, String.valueOf(pn.getPriority())); | ||
67 | - | ||
68 | - // create the array for the neighbors list | ||
69 | - ArrayNode nbrsList = context.mapper().createArrayNode(); | ||
70 | - for (PIMNeighbor nbr : pn.getNeighbors()) { | ||
71 | - nbrsList.add(neighbor(nbr, context)); | ||
72 | - } | ||
73 | - // adds pim neighbor to list | ||
74 | - cp.set(NBRLIST, nbrsList); | ||
75 | - // adds to arraynode which will represent the connect point neighbors hash map. | ||
76 | - cpnList.add(cp); | ||
77 | - } | ||
78 | - pimNbrJsonCodec.set(CPNBRLIST, cpnList); | ||
79 | - return pimNbrJsonCodec; | ||
80 | - } | ||
81 | - | ||
82 | - /** | ||
83 | - * Encode a single PIM Neighbor. | ||
84 | - * | ||
85 | - * @param nbr the neighbor to be encoded | ||
86 | - * @param context encoding context | ||
87 | - * @return the encoded neighbor | ||
88 | - */ | ||
89 | - private ObjectNode neighbor(PIMNeighbor nbr, CodecContext context) { | ||
90 | - return context.mapper().createObjectNode() | ||
91 | - .put(DR, Boolean.toString(nbr.isDr())) | ||
92 | - .put(NBR_IP, nbr.getPrimaryAddr().toString()) | ||
93 | - .put(PR, String.valueOf(nbr.getPriority())) | ||
94 | - .put(HOLDTIME, String.valueOf(nbr.getHoldtime())); | ||
95 | - } | ||
96 | -} |
1 | -/* | ||
2 | - * Copyright 2014-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 reliance 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.onlab.packet.IpAddress; | ||
21 | -import org.onlab.packet.MacAddress; | ||
22 | -import org.onlab.packet.pim.PIMHello; | ||
23 | -import org.onlab.packet.pim.PIMHelloOption; | ||
24 | -import org.onosproject.net.ConnectPoint; | ||
25 | -import org.slf4j.Logger; | ||
26 | - | ||
27 | -import java.nio.ByteBuffer; | ||
28 | -import java.util.concurrent.TimeUnit; | ||
29 | - | ||
30 | -import static com.google.common.base.Preconditions.checkNotNull; | ||
31 | -import static org.slf4j.LoggerFactory.getLogger; | ||
32 | - | ||
33 | -/** | ||
34 | - * PIMNeighbor represents all the PIM routers that have sent us | ||
35 | - * hello messages, or that possibly have been statically configured. | ||
36 | - */ | ||
37 | -public class PIMNeighbor { | ||
38 | - private final Logger log = getLogger(getClass()); | ||
39 | - | ||
40 | - // The primary address of this PIM neighbor | ||
41 | - private IpAddress primaryAddr; | ||
42 | - | ||
43 | - // The MacAddress of this neighbor | ||
44 | - private MacAddress macAddress; | ||
45 | - | ||
46 | - // The ConnectPoint this PIM neighbor is connected to. | ||
47 | - private ConnectPoint connectPoint; | ||
48 | - | ||
49 | - // Is this neighbor us? | ||
50 | - private boolean isThisUs = false; | ||
51 | - | ||
52 | - // The option values this neighbor has sent us. | ||
53 | - private int priority = 0; | ||
54 | - private int genId = 0; | ||
55 | - private short holdtime = 0; | ||
56 | - | ||
57 | - // Is this pim neighbor the DR? | ||
58 | - private boolean isDr = false; | ||
59 | - | ||
60 | - // Timeout for this neighbor | ||
61 | - private volatile Timeout timeout; | ||
62 | - | ||
63 | - // A back pointer the neighbors list this neighbor belongs to. | ||
64 | - private PIMInterface pimInterface; | ||
65 | - | ||
66 | - /** | ||
67 | - * Construct this neighbor from the address and connect point. | ||
68 | - * | ||
69 | - * @param ipaddr IP Address of neighbor | ||
70 | - * @param macaddr MAC Address of the neighbor | ||
71 | - * @param pimInterface The PIMInterface of this neighbor | ||
72 | - */ | ||
73 | - public PIMNeighbor(IpAddress ipaddr, MacAddress macaddr, PIMInterface pimInterface) { | ||
74 | - this.macAddress = macaddr; | ||
75 | - this.primaryAddr = ipaddr; | ||
76 | - this.pimInterface = pimInterface; | ||
77 | - this.resetTimeout(); | ||
78 | - } | ||
79 | - | ||
80 | - /** | ||
81 | - * Get the primary address of this neighbor. | ||
82 | - * | ||
83 | - * @return the primary IP address. | ||
84 | - */ | ||
85 | - public IpAddress getPrimaryAddr() { | ||
86 | - return primaryAddr; | ||
87 | - } | ||
88 | - | ||
89 | - /** | ||
90 | - * Set the primary address of this neighbor. | ||
91 | - * | ||
92 | - * @param primaryAddr the address we'll use when sending hello messages | ||
93 | - */ | ||
94 | - public void setPrimaryAddr(IpAddress primaryAddr) { | ||
95 | - this.primaryAddr = primaryAddr; | ||
96 | - } | ||
97 | - | ||
98 | - /** | ||
99 | - * Get the priority this neighbor has advertised to us. | ||
100 | - * | ||
101 | - * @return the priority | ||
102 | - */ | ||
103 | - public int getPriority() { | ||
104 | - return priority; | ||
105 | - } | ||
106 | - | ||
107 | - /** | ||
108 | - * Set the priority for this neighbor. | ||
109 | - * | ||
110 | - * @param priority This neighbors priority. | ||
111 | - */ | ||
112 | - public void setPriority(int priority) { | ||
113 | - this.priority = priority; | ||
114 | - } | ||
115 | - | ||
116 | - /** | ||
117 | - * Get the generation ID. | ||
118 | - * | ||
119 | - * @return the generation ID. | ||
120 | - */ | ||
121 | - public int getGenId() { | ||
122 | - return genId; | ||
123 | - } | ||
124 | - | ||
125 | - /** | ||
126 | - * Set the generation ID. | ||
127 | - * | ||
128 | - * @param genId the generation ID. | ||
129 | - */ | ||
130 | - public void setGenId(int genId) { | ||
131 | - this.genId = genId; | ||
132 | - } | ||
133 | - | ||
134 | - /** | ||
135 | - * Get the holdtime for this neighbor. | ||
136 | - * | ||
137 | - * @return the holdtime | ||
138 | - */ | ||
139 | - public short getHoldtime() { | ||
140 | - return holdtime; | ||
141 | - } | ||
142 | - | ||
143 | - /** | ||
144 | - * Set the holdtime for this neighbor. | ||
145 | - * | ||
146 | - * @param holdtime the holdtime. | ||
147 | - */ | ||
148 | - public void setholdtime(short holdtime) { | ||
149 | - this.holdtime = holdtime; | ||
150 | - } | ||
151 | - | ||
152 | - /** | ||
153 | - * Is this neighbor the designated router on this connect point? | ||
154 | - * | ||
155 | - * @return true if so, false if not. | ||
156 | - */ | ||
157 | - public boolean isDr() { | ||
158 | - return isDr; | ||
159 | - } | ||
160 | - | ||
161 | - /** | ||
162 | - * Set this router as the designated router on this connect point. | ||
163 | - * | ||
164 | - * @param isDr True is this neighbor is the DR false otherwise | ||
165 | - */ | ||
166 | - public void setIsDr(boolean isDr) { | ||
167 | - this.isDr = isDr; | ||
168 | - } | ||
169 | - | ||
170 | - /** | ||
171 | - * The ConnectPoint this neighbor is connected to. | ||
172 | - * | ||
173 | - * @return the ConnectPoint | ||
174 | - */ | ||
175 | - public PIMInterface getPimInterface() { | ||
176 | - return pimInterface; | ||
177 | - } | ||
178 | - | ||
179 | - /** | ||
180 | - * We have received a fresh hello from this neighbor, now we need to process it. | ||
181 | - * Depending on the values received in the the hello options may force a | ||
182 | - * re-election process. | ||
183 | - * | ||
184 | - * We will also refresh the timeout for this neighbor. | ||
185 | - * | ||
186 | - * @param hello copy of the hello we'll be able to extract options from. | ||
187 | - */ | ||
188 | - public void refresh(PIMHello hello) { | ||
189 | - checkNotNull(hello); | ||
190 | - | ||
191 | - boolean reelect = false; | ||
192 | - for (PIMHelloOption opt : hello.getOptions().values()) { | ||
193 | - | ||
194 | - int len = opt.getOptLength(); | ||
195 | - ByteBuffer bb = ByteBuffer.wrap(opt.getValue()); | ||
196 | - | ||
197 | - switch (opt.getOptType()) { | ||
198 | - case PIMHelloOption.OPT_GENID: | ||
199 | - int newid = bb.getInt(); | ||
200 | - if (this.genId != newid) { | ||
201 | - | ||
202 | - // We have a newly rebooted neighbor, this is where we would | ||
203 | - // send them our joins. | ||
204 | - this.genId = newid; | ||
205 | - } | ||
206 | - break; | ||
207 | - | ||
208 | - case PIMHelloOption.OPT_PRIORITY: | ||
209 | - int newpri = bb.getInt(); | ||
210 | - if (this.priority != newpri) { | ||
211 | - | ||
212 | - // The priorities have changed. We may need to re-elect a new DR? | ||
213 | - if (this.isDr || pimInterface.getDesignatedRouter().getPriority() < priority) { | ||
214 | - reelect = true; | ||
215 | - } | ||
216 | - this.priority = newpri; | ||
217 | - } | ||
218 | - break; | ||
219 | - | ||
220 | - case PIMHelloOption.OPT_HOLDTIME: | ||
221 | - short holdtime = bb.getShort(); | ||
222 | - if (this.holdtime != holdtime) { | ||
223 | - this.holdtime = holdtime; | ||
224 | - if (holdtime == 0) { | ||
225 | - // We have a neighbor going down. We can remove all joins | ||
226 | - // we have learned from them. | ||
227 | - | ||
228 | - log.debug("PIM Neighbor has timed out: {}", this.primaryAddr.toString()); | ||
229 | - return; | ||
230 | - } | ||
231 | - } | ||
232 | - break; | ||
233 | - | ||
234 | - case PIMHelloOption.OPT_PRUNEDELAY: | ||
235 | - case PIMHelloOption.OPT_ADDRLIST: | ||
236 | - // TODO: implement prune delay and addr list. Fall through for now. | ||
237 | - | ||
238 | - default: | ||
239 | - log.debug("PIM Hello option type: {} not yet supported or unknown.", opt.getOptType()); | ||
240 | - break; | ||
241 | - } | ||
242 | - } | ||
243 | - | ||
244 | - if (reelect) { | ||
245 | - pimInterface.electDR(this); | ||
246 | - } | ||
247 | - | ||
248 | - // Reset the next timeout timer | ||
249 | - this.resetTimeout(); | ||
250 | - } | ||
251 | - | ||
252 | - /* --------------------------------------- Timer functions -------------------------- */ | ||
253 | - | ||
254 | - /** | ||
255 | - * Restart the timeout task for this neighbor. | ||
256 | - */ | ||
257 | - private void resetTimeout() { | ||
258 | - | ||
259 | - if (this.holdtime == 0) { | ||
260 | - | ||
261 | - // Prepare to die. | ||
262 | - log.debug("shutting down timer for nbr {}", this.primaryAddr.toString()); | ||
263 | - if (this.timeout != null) { | ||
264 | - this.timeout.cancel(); | ||
265 | - this.timeout = null; | ||
266 | - } | ||
267 | - return; | ||
268 | - } | ||
269 | - | ||
270 | - // Cancel the existing timeout and start a fresh new one. | ||
271 | - if (this.timeout != null) { | ||
272 | - this.timeout.cancel(); | ||
273 | - } | ||
274 | - | ||
275 | - this.timeout = PIMTimer.getTimer().newTimeout(new NeighborTimeoutTask(this), holdtime, TimeUnit.SECONDS); | ||
276 | - } | ||
277 | - | ||
278 | - /** | ||
279 | - * The task to run when a neighbor timeout expires. | ||
280 | - */ | ||
281 | - private final class NeighborTimeoutTask implements TimerTask { | ||
282 | - PIMNeighbor nbr; | ||
283 | - | ||
284 | - NeighborTimeoutTask(PIMNeighbor nbr) { | ||
285 | - this.nbr = nbr; | ||
286 | - } | ||
287 | - | ||
288 | - @Override | ||
289 | - public void run(Timeout timeout) throws Exception { | ||
290 | - | ||
291 | - log.debug("PIM Neighbor {} has timed out: ", nbr.toString()); | ||
292 | - nbr.pimInterface.removeNeighbor(nbr); | ||
293 | - } | ||
294 | - } | ||
295 | - | ||
296 | - /** | ||
297 | - * Stop the timeout timer. | ||
298 | - * | ||
299 | - * This happens when we remove the neighbor. | ||
300 | - */ | ||
301 | - private final void stopTimeout() { | ||
302 | - this.timeout.cancel(); | ||
303 | - this.timeout = null; | ||
304 | - } | ||
305 | - | ||
306 | - @Override | ||
307 | - public String toString() { | ||
308 | - String out = ""; | ||
309 | - if (this.isDr) { | ||
310 | - out += "*NBR:"; | ||
311 | - } else { | ||
312 | - out += "NBR:"; | ||
313 | - } | ||
314 | - out += "\tIP: " + this.primaryAddr.toString(); | ||
315 | - out += "\tPr: " + String.valueOf(this.priority); | ||
316 | - out += "\tHoldTime: " + String.valueOf(this.holdtime); | ||
317 | - out += "\tGenID: " + String.valueOf(this.genId) + "\n"; | ||
318 | - return out; | ||
319 | - } | ||
320 | -} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -17,213 +17,74 @@ package org.onosproject.pim.impl; | ... | @@ -17,213 +17,74 @@ package org.onosproject.pim.impl; |
17 | 17 | ||
18 | import org.onlab.packet.Ethernet; | 18 | import org.onlab.packet.Ethernet; |
19 | import org.onlab.packet.IPv4; | 19 | import org.onlab.packet.IPv4; |
20 | -import org.onlab.packet.Ip4Address; | ||
21 | import org.onlab.packet.IpAddress; | 20 | import org.onlab.packet.IpAddress; |
22 | -import org.onlab.packet.IpPrefix; | ||
23 | -import org.onlab.packet.MacAddress; | ||
24 | import org.onlab.packet.PIM; | 21 | 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; | 22 | import org.slf4j.Logger; |
41 | 23 | ||
42 | -import java.nio.ByteBuffer; | ||
43 | - | ||
44 | import static com.google.common.base.Preconditions.checkNotNull; | 24 | import static com.google.common.base.Preconditions.checkNotNull; |
45 | import static org.slf4j.LoggerFactory.getLogger; | 25 | import static org.slf4j.LoggerFactory.getLogger; |
46 | 26 | ||
47 | /** | 27 | /** |
48 | - * Handing Incoming and outgoing PIM packets. | 28 | + * This class will process PIM packets. |
49 | */ | 29 | */ |
50 | -public final class PIMPacketHandler { | 30 | +public 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 | 31 | ||
62 | - public static PIMPacketHandler getInstance() { | 32 | + private final Logger log = getLogger(getClass()); |
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 | 33 | ||
87 | /** | 34 | /** |
88 | - * Shutdown the packet handling service. | 35 | + * Constructor for this class. |
89 | */ | 36 | */ |
90 | - public void stop() { | 37 | + public PIMPacketHandler() { |
91 | - packetService.removeProcessor(processor); | ||
92 | - processor = null; | ||
93 | } | 38 | } |
94 | 39 | ||
95 | /** | 40 | /** |
96 | - * Packet processor responsible for handling IGMP packets. | 41 | + * Sanitize and process the packet. |
42 | + * TODO: replace ConnectPoint with PIMInterface when PIMInterface has been added. | ||
43 | + * | ||
44 | + * @param ethPkt the packet starting with the Ethernet header. | ||
45 | + * @param pimi the PIM Interface the packet arrived on. | ||
97 | */ | 46 | */ |
98 | - public class PIMPacketProcessor implements PacketProcessor { | 47 | + public void processPacket(Ethernet ethPkt, PIMInterface pimi) { |
99 | - private final Logger log = getLogger(getClass()); | 48 | + checkNotNull(ethPkt); |
100 | - | 49 | + checkNotNull(pimi); |
101 | - @Override | 50 | + |
102 | - public void process(PacketContext context) { | 51 | + // Sanitize the ethernet header to ensure it is IPv4. IPv6 we'll deal with later |
103 | - // Stop processing if the packet has been handled, since we | 52 | + if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) { |
104 | - // can't do any more to it. | 53 | + log.debug("Recieved a non IPv4 packet"); |
105 | - if (context.isHandled()) { | 54 | + return; |
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 | } | 55 | } |
168 | 56 | ||
169 | - /** | 57 | + // Get the IP header |
170 | - * Process incoming hello message, we will need the Macaddress and IP address of the sender. | 58 | + IPv4 ip = (IPv4) ethPkt.getPayload(); |
171 | - * | 59 | + if (ip.getProtocol() != IPv4.PROTOCOL_PIM) { |
172 | - * @param ethPkt the ethernet header | 60 | + log.debug("Received a non PIM IP packet"); |
173 | - * @param receivedFrom the connect point we recieved this message from | 61 | + return; |
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 | } | 62 | } |
188 | - } | ||
189 | 63 | ||
190 | - // Create an ethernet header and serialize then send | 64 | + // Get the address of our the neighbor that sent this packet to us. |
191 | - public void sendPacket(PIM pim, PIMInterface pimIntf) { | 65 | + IpAddress nbraddr = IpAddress.valueOf(ip.getDestinationAddress()); |
66 | + log.debug("Packet " + nbraddr.toString() + " received on port " + pimi.toString()); | ||
192 | 67 | ||
193 | - Interface theInterface = pimIntf.getInterface(); | 68 | + // Get the PIM header |
69 | + PIM pim = (PIM) ip.getPayload(); | ||
70 | + checkNotNull(pim); | ||
194 | 71 | ||
195 | - // Create the ethernet packet | 72 | + // Process the pim packet |
196 | - Ethernet eth = new Ethernet(); | 73 | + switch (pim.getPimMsgType()) { |
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 | 74 | ||
215 | - // Now set pim | 75 | + case PIM.TYPE_HELLO: |
216 | - ip.setPayload(pim); | 76 | + pimi.processHello(ethPkt); |
217 | - pim.setParent(ip); | 77 | + log.debug("Received a PIM hello packet"); |
78 | + break; | ||
218 | 79 | ||
219 | - ConnectPoint cp = theInterface.connectPoint(); | 80 | + case PIM.TYPE_JOIN_PRUNE_REQUEST: |
220 | - checkNotNull(cp); | 81 | + pimi.processJoinPrune(ethPkt); |
82 | + log.debug("Received a PIM Join/Prune message"); | ||
83 | + break; | ||
221 | 84 | ||
222 | - TrafficTreatment treat = DefaultTrafficTreatment.builder().setOutput(cp.port()).build(); | 85 | + default: |
223 | - ByteBuffer bb = ByteBuffer.wrap(eth.serialize()); | 86 | + log.debug("Recieved unsupported PIM type: " + pim.getPimMsgType()); |
224 | - OutboundPacket packet = new DefaultOutboundPacket(cp.deviceId(), treat, bb); | 87 | + break; |
225 | - checkNotNull(packet); | 88 | + } |
226 | - | ||
227 | - packetService.emit(packet); | ||
228 | } | 89 | } |
229 | } | 90 | } | ... | ... |
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.HashedWheelTimer; | ||
19 | - | ||
20 | -import static com.google.common.base.Preconditions.checkNotNull; | ||
21 | - | ||
22 | -/** | ||
23 | - * PIM Timer used for PIM Neighbors. | ||
24 | - */ | ||
25 | -public final class PIMTimer { | ||
26 | - | ||
27 | - private static volatile HashedWheelTimer timer; | ||
28 | - | ||
29 | - // Ban public construction | ||
30 | - private PIMTimer() { | ||
31 | - } | ||
32 | - | ||
33 | - /** | ||
34 | - * Returns the singleton hashed-wheel timer. | ||
35 | - * | ||
36 | - * @return hashed-wheel timer | ||
37 | - */ | ||
38 | - public static HashedWheelTimer getTimer() { | ||
39 | - if (PIMTimer.timer == null) { | ||
40 | - initTimer(); | ||
41 | - } | ||
42 | - return PIMTimer.timer; | ||
43 | - } | ||
44 | - | ||
45 | - // Start the PIM timer. | ||
46 | - private static synchronized void initTimer() { | ||
47 | - if (PIMTimer.timer == null) { | ||
48 | - | ||
49 | - // Create and start a new hashed wheel timer, if it does not exist. | ||
50 | - HashedWheelTimer hwTimer = new HashedWheelTimer(); | ||
51 | - hwTimer.start(); | ||
52 | - PIMTimer.timer = hwTimer; | ||
53 | - } | ||
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 | - } | ||
72 | -} |
... | @@ -53,7 +53,6 @@ import java.util.stream.Collectors; | ... | @@ -53,7 +53,6 @@ import java.util.stream.Collectors; |
53 | 53 | ||
54 | import static org.slf4j.LoggerFactory.getLogger; | 54 | import static org.slf4j.LoggerFactory.getLogger; |
55 | 55 | ||
56 | - | ||
57 | /** | 56 | /** |
58 | * Provides implementation of the meter service APIs. | 57 | * Provides implementation of the meter service APIs. |
59 | */ | 58 | */ | ... | ... |
-
Please register or login to post a comment