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
506 additions
and
1274 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 | -} |
... | @@ -17,325 +17,178 @@ package org.onosproject.pim.impl; | ... | @@ -17,325 +17,178 @@ 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.MacAddress; | 21 | import org.onlab.packet.MacAddress; |
23 | import org.onlab.packet.PIM; | 22 | import org.onlab.packet.PIM; |
24 | import org.onlab.packet.pim.PIMHello; | 23 | import org.onlab.packet.pim.PIMHello; |
25 | import org.onlab.packet.pim.PIMHelloOption; | 24 | import org.onlab.packet.pim.PIMHelloOption; |
26 | import org.onosproject.incubator.net.intf.Interface; | 25 | import org.onosproject.incubator.net.intf.Interface; |
27 | -import org.onosproject.net.ConnectPoint; | ||
28 | import org.onosproject.net.host.InterfaceIpAddress; | 26 | import org.onosproject.net.host.InterfaceIpAddress; |
29 | import org.slf4j.Logger; | 27 | import org.slf4j.Logger; |
30 | -import org.slf4j.LoggerFactory; | ||
31 | 28 | ||
32 | -import java.util.Collection; | 29 | +import java.util.Set; |
33 | -import java.util.HashMap; | ||
34 | -import java.util.Map; | ||
35 | 30 | ||
36 | -import static com.google.common.base.Preconditions.checkNotNull; | 31 | +import static org.slf4j.LoggerFactory.getLogger; |
37 | 32 | ||
38 | /** | 33 | /** |
39 | - * The PIM Interface is a wrapper around a ConnectPoint and used to provide | 34 | + * PIM Interface represents an ONOS Interface with IP & MAC addresses for |
40 | - * hello options values when "talking" with PIM other PIM routers. | 35 | + * a given ConnectPoint. |
41 | */ | 36 | */ |
42 | public class PIMInterface { | 37 | public class PIMInterface { |
43 | - private static Logger log = LoggerFactory.getLogger("PIMInterfaces"); | ||
44 | 38 | ||
45 | - // Interface from the interface subsystem | 39 | + private final Logger log = getLogger(getClass()); |
46 | - private Interface theInterface; | ||
47 | 40 | ||
48 | - // The list of PIM neighbors adjacent to this interface | 41 | + private Interface onosInterface; |
49 | - private Map<IpAddress, PIMNeighbor> neighbors = new HashMap<>(); | ||
50 | 42 | ||
51 | - // The designatedRouter for this LAN | 43 | + // Our hello opt holdtime |
52 | - private PIMNeighbor designatedRouter; | 44 | + private short holdtime = PIMHelloOption.DEFAULT_HOLDTIME; |
53 | 45 | ||
54 | - // The priority we use on this ConnectPoint. | 46 | + // Our hello opt prune delay |
55 | - private int priority = PIMHelloOption.DEFAULT_PRIORITY; | 47 | + private int pruneDelay = PIMHelloOption.DEFAULT_PRUNEDELAY; |
56 | - | ||
57 | - // The holdtime we are sending out. | ||
58 | - private int holdtime = PIMHelloOption.DEFAULT_HOLDTIME; | ||
59 | 48 | ||
60 | - // Then generation ID we are sending out. 0 means we need to generate a new random ID | 49 | + // Neighbor priority |
61 | - private int genid = PIMHelloOption.DEFAULT_GENID; | 50 | + private int priority = PIMHelloOption.DEFAULT_PRIORITY; |
62 | 51 | ||
63 | - // Our default prune delay | 52 | + // Our current genid |
64 | - private int prunedelay = PIMHelloOption.DEFAULT_PRUNEDELAY; | 53 | + private int genid = PIMHelloOption.DEFAULT_GENID; // Needs to be assigned. |
65 | 54 | ||
66 | /** | 55 | /** |
67 | - * Create a PIMInterface. | 56 | + * Create a PIMInterface from an ONOS Interface. |
68 | * | 57 | * |
69 | - * @param intf the network interface configuration | 58 | + * @param intf the ONOS Interface. |
70 | */ | 59 | */ |
71 | public PIMInterface(Interface intf) { | 60 | public PIMInterface(Interface intf) { |
72 | - | 61 | + onosInterface = intf; |
73 | - log.debug("Adding an interface: " + intf.toString() + "\n"); | ||
74 | - this.theInterface = intf; | ||
75 | - | ||
76 | - // Send a hello to let our neighbors know we are alive | ||
77 | - sendHello(); | ||
78 | } | 62 | } |
79 | 63 | ||
80 | /** | 64 | /** |
81 | - * Get the PIM Interface. | 65 | + * Return the ONOS Interface. |
82 | * | 66 | * |
83 | - * @return the PIM Interface | 67 | + * @return ONOS Interface. |
84 | */ | 68 | */ |
85 | public Interface getInterface() { | 69 | public Interface getInterface() { |
86 | - return theInterface; | 70 | + return this.onosInterface; |
87 | } | 71 | } |
88 | 72 | ||
89 | /** | 73 | /** |
90 | - * Getter for our IP address. | 74 | + * Set the ONOS Interface, it will override a previous value. |
91 | * | 75 | * |
92 | - * @return our IP address. | 76 | + * @param intf ONOS Interface. |
93 | */ | 77 | */ |
94 | - public IpAddress getIpAddress() { | 78 | + public PIMInterface setInterface(Interface intf) { |
95 | - if (theInterface.ipAddresses().isEmpty()) { | 79 | + this.onosInterface = intf; |
96 | - return null; | 80 | + return this; |
97 | - } | ||
98 | - | ||
99 | - // We will just assume the first interface on the list | ||
100 | - IpAddress ipaddr = null; | ||
101 | - for (InterfaceIpAddress ifipaddr : theInterface.ipAddresses()) { | ||
102 | - ipaddr = ifipaddr.ipAddress(); | ||
103 | - break; | ||
104 | - } | ||
105 | - return ipaddr; | ||
106 | } | 81 | } |
107 | 82 | ||
108 | /** | 83 | /** |
109 | - * Get our priority. | 84 | + * Get the set of IP Addresses associated with this interface. |
110 | * | 85 | * |
111 | - * @return our priority. | 86 | + * @return a set of Ip Addresses on this interface |
112 | */ | 87 | */ |
113 | - public int getPriority() { | 88 | + public Set<InterfaceIpAddress> getIpAddresses() { |
114 | - return this.priority; | 89 | + return this.onosInterface.ipAddresses(); |
115 | } | 90 | } |
116 | 91 | ||
117 | /** | 92 | /** |
118 | - * Get the designated router on this connection. | 93 | + * Return a single "best" IP address. |
119 | * | 94 | * |
120 | - * @return the PIMNeighbor representing the DR | 95 | + * @return the choosen IP address or null if none |
121 | */ | 96 | */ |
122 | - public PIMNeighbor getDesignatedRouter() { | 97 | + public IpAddress getIpAddress() { |
123 | - return designatedRouter; | 98 | + if (onosInterface.ipAddresses().isEmpty()) { |
99 | + return null; | ||
124 | } | 100 | } |
125 | 101 | ||
126 | - /** | 102 | + IpAddress ipaddr = null; |
127 | - * Are we the DR on this CP? | 103 | + for (InterfaceIpAddress ifipaddr : onosInterface.ipAddresses()) { |
128 | - * | 104 | + ipaddr = ifipaddr.ipAddress(); |
129 | - * @return true if we are, false if not | 105 | + break; |
130 | - */ | ||
131 | - public boolean areWeDr() { | ||
132 | - return (designatedRouter != null && | ||
133 | - designatedRouter.getPrimaryAddr().equals(this.getIpAddress())); | ||
134 | } | 106 | } |
135 | - | 107 | + return ipaddr; |
136 | - /** | ||
137 | - * Return a collection of PIM Neighbors. | ||
138 | - * | ||
139 | - * @return the collection of PIM Neighbors | ||
140 | - */ | ||
141 | - public Collection<PIMNeighbor> getNeighbors() { | ||
142 | - return this.neighbors.values(); | ||
143 | } | 108 | } |
144 | 109 | ||
145 | /** | 110 | /** |
146 | - * Find the neighbor with the given IP address on this CP. | 111 | + * Get the holdtime. |
147 | * | 112 | * |
148 | - * @param ipaddr the IP address of the neighbor we are interested in | 113 | + * @return the holdtime |
149 | - * @return the pim neighbor if it exists | ||
150 | */ | 114 | */ |
151 | - public PIMNeighbor findNeighbor(IpAddress ipaddr) { | 115 | + public short getHoldtime() { |
152 | - PIMNeighbor nbr = neighbors.get(ipaddr); | 116 | + return this.holdtime; |
153 | - return nbr; | ||
154 | } | 117 | } |
155 | 118 | ||
156 | /** | 119 | /** |
157 | - * Add a new PIM neighbor to this list. | 120 | + * Get the prune delay. |
158 | * | 121 | * |
159 | - * @param nbr the neighbor to be added. | 122 | + * @return The prune delay |
160 | */ | 123 | */ |
161 | - public void addNeighbor(PIMNeighbor nbr) { | 124 | + public int getPruneDelay() { |
162 | - if (neighbors.containsKey(nbr.getPrimaryAddr())) { | 125 | + return this.pruneDelay; |
163 | - | ||
164 | - log.debug("We are adding a neighbor that already exists: {}", nbr.toString()); | ||
165 | - neighbors.remove(nbr.getPrimaryAddr()); | ||
166 | - } | ||
167 | - neighbors.put(nbr.getPrimaryAddr(), nbr); | ||
168 | } | 126 | } |
169 | 127 | ||
170 | /** | 128 | /** |
171 | - * Remove the neighbor from our neighbor list. | 129 | + * Get our hello priority. |
172 | * | 130 | * |
173 | - * @param ipaddr the IP address of the neighbor to remove | 131 | + * @return our priority |
174 | */ | 132 | */ |
175 | - public void removeNeighbor(IpAddress ipaddr) { | 133 | + public int getPriority() { |
176 | - | 134 | + return this.priority; |
177 | - if (neighbors.containsKey(ipaddr)) { | ||
178 | - neighbors.remove(ipaddr); | ||
179 | - } | ||
180 | - this.electDR(); | ||
181 | } | 135 | } |
182 | 136 | ||
183 | /** | 137 | /** |
184 | - * Remove the given neighbor from the neighbor list. | 138 | + * Get our generation ID. |
185 | * | 139 | * |
186 | - * @param nbr the nbr to be removed. | 140 | + * @return our generation ID |
187 | */ | 141 | */ |
188 | - public void removeNeighbor(PIMNeighbor nbr) { | 142 | + public int getGenid() { |
189 | - | 143 | + return this.genid; |
190 | - neighbors.remove(nbr.getPrimaryAddr(), nbr); | ||
191 | - this.electDR(); | ||
192 | } | 144 | } |
193 | 145 | ||
194 | /** | 146 | /** |
195 | - * Elect a new DR on this ConnectPoint. | 147 | + * Process an incoming PIM Hello message. |
196 | * | 148 | * |
197 | - * @return the PIM Neighbor that wins | 149 | + * @param ethPkt the Ethernet packet header |
198 | */ | 150 | */ |
199 | - public PIMNeighbor electDR() { | 151 | + public void processHello(Ethernet ethPkt) { |
200 | 152 | ||
201 | - for (PIMNeighbor nbr : this.neighbors.values()) { | 153 | + // We'll need to save our neighbors MAC address |
202 | - if (this.designatedRouter == null) { | 154 | + MacAddress nbrmac = ethPkt.getSourceMAC(); |
203 | - this.designatedRouter = nbr; | ||
204 | - continue; | ||
205 | - } | ||
206 | 155 | ||
207 | - if (nbr.getPriority() > this.designatedRouter.getPriority()) { | 156 | + // And we'll need to save neighbors IP Address. |
208 | - this.designatedRouter = nbr; | 157 | + IPv4 iphdr = (IPv4) ethPkt.getPayload(); |
209 | - continue; | 158 | + IpAddress srcip = IpAddress.valueOf(iphdr.getSourceAddress()); |
210 | - } | ||
211 | 159 | ||
212 | - // We could sort in ascending order | 160 | + PIM pimhdr = (PIM) iphdr.getPayload(); |
213 | - if (this.designatedRouter.getPrimaryAddr().compareTo(nbr.getPrimaryAddr()) > 0) { | 161 | + if (pimhdr.getPimMsgType() != PIM.TYPE_HELLO) { |
214 | - this.designatedRouter = nbr; | 162 | + log.error("process Hello has received a non hello packet type: " + pimhdr.getPimMsgType()); |
215 | - continue; | 163 | + return; |
216 | - } | ||
217 | - } | ||
218 | - | ||
219 | - return this.designatedRouter; | ||
220 | - } | ||
221 | - | ||
222 | - /** | ||
223 | - * Elect a new DR given the new neighbor. | ||
224 | - * | ||
225 | - * @param nbr the new neighbor to use in DR election. | ||
226 | - * @return the PIM Neighbor that wins DR election | ||
227 | - */ | ||
228 | - public PIMNeighbor electDR(PIMNeighbor nbr) { | ||
229 | - | ||
230 | - // Make sure I have | ||
231 | - if (this.designatedRouter == null || | ||
232 | - this.designatedRouter.getPriority() < nbr.getPriority() || | ||
233 | - this.designatedRouter.getPrimaryAddr().compareTo(nbr.getPrimaryAddr()) > 0) { | ||
234 | - this.designatedRouter = nbr; | ||
235 | - } | ||
236 | - return this.designatedRouter; | ||
237 | - } | ||
238 | - | ||
239 | - /** | ||
240 | - * Find or create a pim neighbor with a given ip address and connect point. | ||
241 | - * | ||
242 | - * @param ipaddr of the pim neighbor | ||
243 | - * @param mac The mac address of our sending neighbor | ||
244 | - * @return an existing or new PIM neighbor | ||
245 | - */ | ||
246 | - public PIMNeighbor findOrCreate(IpAddress ipaddr, MacAddress mac) { | ||
247 | - PIMNeighbor nbr = this.findNeighbor(ipaddr); | ||
248 | - if (nbr == null) { | ||
249 | - nbr = new PIMNeighbor(ipaddr, mac, this); | ||
250 | - this.addNeighbor(nbr); | ||
251 | - this.electDR(nbr); | ||
252 | - } | ||
253 | - return nbr; | ||
254 | } | 164 | } |
255 | 165 | ||
256 | - /** | 166 | + // TODO: Maybe a good idea to check the checksum. Let's jump into the hello options. |
257 | - * Process a hello packet received on this Interface. | 167 | + PIMHello hello = (PIMHello) pimhdr.getPayload(); |
258 | - * | ||
259 | - * @param ethPkt the ethernet packet containing the hello message | ||
260 | - * @param cp the ConnectPoint of this interface | ||
261 | - */ | ||
262 | - public void processHello(Ethernet ethPkt, ConnectPoint cp) { | ||
263 | - checkNotNull(ethPkt); | ||
264 | - checkNotNull(cp); | ||
265 | 168 | ||
266 | - MacAddress srcmac = ethPkt.getSourceMAC(); | 169 | + // TODO: this is about where we find or create our PIMNeighbor |
267 | - IPv4 ip = (IPv4) ethPkt.getPayload(); | ||
268 | - Ip4Address srcip = Ip4Address.valueOf(ip.getSourceAddress()); | ||
269 | 170 | ||
270 | - PIM pim = (PIM) ip.getPayload(); | 171 | + boolean reElectDr = false; |
271 | - checkNotNull(pim); | ||
272 | 172 | ||
273 | - PIMHello hello = (PIMHello) pim.getPayload(); | 173 | + // Start walking through all the hello options to handle accordingly. |
274 | - checkNotNull(hello); | 174 | + for (PIMHelloOption opt : hello.getOptions().values()) { |
275 | 175 | ||
276 | - PIMNeighbor nbr = this.findOrCreate(srcip, srcmac); | 176 | + // TODO: This is where we handle the options and modify the neighbor accordingly. |
277 | - if (nbr == null) { | 177 | + // We'll need to create the PIMNeighbor class next. Depending on what happens |
278 | - log.error("Could not create a neighbor for: {1}", srcip.toString()); | 178 | + // we may need to re-elect a DR |
279 | - return; | ||
280 | } | 179 | } |
281 | 180 | ||
282 | - ConnectPoint icp = theInterface.connectPoint(); | 181 | + if (reElectDr) { |
283 | - checkNotNull(icp); | 182 | + // TODO: create an election() method and call it here with a PIMNeighbor |
284 | - if (!cp.equals(icp)) { | ||
285 | - log.error("PIM Hello message received from {} on incorrect interface {}", | ||
286 | - nbr.getPrimaryAddr(), this.toString()); | ||
287 | - return; | ||
288 | } | 183 | } |
289 | - nbr.refresh(hello); | ||
290 | } | 184 | } |
291 | 185 | ||
292 | /** | 186 | /** |
293 | - * Send a hello packet from this interface. | 187 | + * Process an incoming PIM JoinPrune message. |
294 | - */ | ||
295 | - public void sendHello() { | ||
296 | - PIM pim = new PIM(); | ||
297 | - PIMHello hello = new PIMHello(); | ||
298 | - | ||
299 | - // Create a PIM Hello | ||
300 | - pim = new PIM(); | ||
301 | - pim.setVersion((byte) 2); | ||
302 | - pim.setPIMType((byte) PIM.TYPE_HELLO); | ||
303 | - pim.setChecksum((short) 0); | ||
304 | - | ||
305 | - hello = new PIMHello(); | ||
306 | - hello.createDefaultOptions(); | ||
307 | - pim.setPayload(hello); | ||
308 | - hello.setParent(pim); | ||
309 | - | ||
310 | - log.debug("Sending hello: \n"); | ||
311 | - PIMPacketHandler.getInstance().sendPacket(pim, this); | ||
312 | - } | ||
313 | - | ||
314 | - /** | ||
315 | - * prints the connectPointNeighbors list with each neighbor list. | ||
316 | * | 188 | * |
317 | - * @return string of neighbors. | 189 | + * @param ethPkt the Ethernet packet header. |
318 | */ | 190 | */ |
319 | - public String printNeighbors() { | 191 | + public void processJoinPrune(Ethernet ethPkt) { |
320 | - String out = "PIM Neighbors Table: \n"; | ||
321 | - for (PIMNeighbor nbr : this.neighbors.values()) { | ||
322 | - out += "\t" + nbr.toString(); | ||
323 | - } | ||
324 | - return out; | ||
325 | - } | ||
326 | 192 | ||
327 | - @Override | ||
328 | - public String toString() { | ||
329 | - IpAddress ipaddr = this.getIpAddress(); | ||
330 | - String out = "PIM Neighbors: "; | ||
331 | - if (ipaddr != null) { | ||
332 | - out += "IP: " + ipaddr.toString(); | ||
333 | - } else { | ||
334 | - out += "IP: *Null*"; | ||
335 | - } | ||
336 | - out += "\tPR: " + String.valueOf(this.priority) + "\n"; | ||
337 | - return out; | ||
338 | } | 193 | } |
339 | - | ||
340 | } | 194 | } |
341 | - | ... | ... |
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 | - | ||
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 | 31 | ||
84 | - packetService.addProcessor(processor, PacketProcessor.director(1)); | 32 | + private final Logger log = getLogger(getClass()); |
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 | ||
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 | 50 | ||
119 | - /* | 51 | + // Sanitize the ethernet header to ensure it is IPv4. IPv6 we'll deal with later |
120 | - * IPv6 MLD packets are handled by ICMP6. We'll only deal | ||
121 | - * with IPv4. | ||
122 | - */ | ||
123 | if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) { | 52 | if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) { |
53 | + log.debug("Recieved a non IPv4 packet"); | ||
124 | return; | 54 | return; |
125 | } | 55 | } |
126 | 56 | ||
57 | + // Get the IP header | ||
127 | IPv4 ip = (IPv4) ethPkt.getPayload(); | 58 | 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) { | 59 | if (ip.getProtocol() != IPv4.PROTOCOL_PIM) { |
134 | - log.debug("PIM Picked up a non PIM packet: IP protocol: " + ip.getProtocol()); | 60 | + log.debug("Received a non PIM IP packet"); |
135 | return; | 61 | return; |
136 | } | 62 | } |
137 | 63 | ||
138 | - // TODO: check incoming to be PIM.PIM_ADDRESS or "Our" address. | 64 | + // Get the address of our the neighbor that sent this packet to us. |
139 | - IpPrefix spfx = IpPrefix.valueOf(saddr, 32); | 65 | + IpAddress nbraddr = IpAddress.valueOf(ip.getDestinationAddress()); |
140 | - IpPrefix gpfx = IpPrefix.valueOf(gaddr, 32); | 66 | + log.debug("Packet " + nbraddr.toString() + " received on port " + pimi.toString()); |
141 | 67 | ||
68 | + // Get the PIM header | ||
142 | PIM pim = (PIM) ip.getPayload(); | 69 | PIM pim = (PIM) ip.getPayload(); |
70 | + checkNotNull(pim); | ||
71 | + | ||
72 | + // Process the pim packet | ||
143 | switch (pim.getPimMsgType()) { | 73 | switch (pim.getPimMsgType()) { |
144 | 74 | ||
145 | case PIM.TYPE_HELLO: | 75 | case PIM.TYPE_HELLO: |
146 | - processHello(ethPkt, context.inPacket().receivedFrom()); | 76 | + pimi.processHello(ethPkt); |
77 | + log.debug("Received a PIM hello packet"); | ||
147 | break; | 78 | break; |
148 | 79 | ||
149 | case PIM.TYPE_JOIN_PRUNE_REQUEST: | 80 | case PIM.TYPE_JOIN_PRUNE_REQUEST: |
150 | - // Create the function | 81 | + pimi.processJoinPrune(ethPkt); |
151 | - break; | 82 | + log.debug("Received a PIM Join/Prune message"); |
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; | 83 | break; |
162 | 84 | ||
163 | default: | 85 | default: |
164 | - log.debug("Unkown PIM message type: " + pim.getPimMsgType()); | 86 | + log.debug("Recieved unsupported PIM type: " + pim.getPimMsgType()); |
165 | break; | 87 | break; |
166 | } | 88 | } |
167 | } | 89 | } |
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 | } | 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