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