diff options
Diffstat (limited to 'framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java')
-rw-r--r-- | framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java new file mode 100644 index 00000000..28d1e8ba --- /dev/null +++ b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java @@ -0,0 +1,339 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.pim.impl; + +import org.onlab.packet.Ethernet; +import org.onlab.packet.IPv4; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; +import org.onlab.packet.PIM; +import org.onlab.packet.pim.PIMHello; +import org.onlab.packet.pim.PIMHelloOption; +import org.onosproject.incubator.net.intf.Interface; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.host.InterfaceIpAddress; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * The PIM Interface is a wrapper around a ConnectPoint and used to provide + * hello options values when "talking" with PIM other PIM routers. + */ +public class PIMInterface { + private static Logger log = LoggerFactory.getLogger("PIMInterfaces"); + + // Interface from the interface subsystem + private Interface theInterface; + + // The list of PIM neighbors adjacent to this interface + private Map<IpAddress, PIMNeighbor> neighbors = new HashMap<>(); + + // The designatedRouter for this LAN + private PIMNeighbor designatedRouter; + + // The priority we use on this ConnectPoint. + private int priority = PIMHelloOption.DEFAULT_PRIORITY; + + // The holdtime we are sending out. + private int holdtime = PIMHelloOption.DEFAULT_HOLDTIME; + + // Then generation ID we are sending out. 0 means we need to generate a new random ID + private int genid = PIMHelloOption.DEFAULT_GENID; + + // Our default prune delay + private int prunedelay = PIMHelloOption.DEFAULT_PRUNEDELAY; + + /** + * Create a PIMInterface. + */ + public PIMInterface(Interface intf) { + + log.debug("Adding an interface: " + intf.toString() + "\n"); + this.theInterface = intf; + + // Send a hello to let our neighbors know we are alive + sendHello(); + } + + /** + * Get the PIM Interface. + * + * @return the PIM Interface + */ + public Interface getInterface() { + return theInterface; + } + + /** + * Getter for our IP address. + * + * @return our IP address. + */ + public IpAddress getIpAddress() { + if (theInterface.ipAddresses().isEmpty()) { + return null; + } + + // We will just assume the first interface on the list + IpAddress ipaddr = null; + for (InterfaceIpAddress ifipaddr : theInterface.ipAddresses()) { + ipaddr = ifipaddr.ipAddress(); + break; + } + return ipaddr; + } + + /** + * Get our priority. + * + * @return our priority. + */ + public int getPriority() { + return this.priority; + } + + /** + * Get the designated router on this connection. + * + * @return the PIMNeighbor representing the DR + */ + public PIMNeighbor getDesignatedRouter() { + return designatedRouter; + } + + /** + * Are we the DR on this CP? + * + * @return true if we are, false if not + */ + public boolean areWeDr() { + return (designatedRouter != null && + designatedRouter.getPrimaryAddr().equals(this.getIpAddress())); + } + + /** + * Return a collection of PIM Neighbors. + * + * @return the collection of PIM Neighbors + */ + public Collection<PIMNeighbor> getNeighbors() { + return this.neighbors.values(); + } + + /** + * Find the neighbor with the given IP address on this CP. + * + * @param ipaddr the IP address of the neighbor we are interested in + * @return the pim neighbor if it exists + */ + public PIMNeighbor findNeighbor(IpAddress ipaddr) { + PIMNeighbor nbr = neighbors.get(ipaddr); + return nbr; + } + + /** + * Add a new PIM neighbor to this list. + * + * @param nbr the neighbor to be added. + */ + public void addNeighbor(PIMNeighbor nbr) { + if (neighbors.containsKey(nbr.getPrimaryAddr())) { + + log.debug("We are adding a neighbor that already exists: {}", nbr.toString()); + neighbors.remove(nbr.getPrimaryAddr()); + } + neighbors.put(nbr.getPrimaryAddr(), nbr); + } + + /** + * Remove the neighbor from our neighbor list. + * + * @param ipaddr the IP address of the neighbor to remove + */ + public void removeNeighbor(IpAddress ipaddr) { + + if (neighbors.containsKey(ipaddr)) { + neighbors.remove(ipaddr); + } + this.electDR(); + } + + /** + * Remove the given neighbor from the neighbor list. + * + * @param nbr the nbr to be removed. + */ + public void removeNeighbor(PIMNeighbor nbr) { + + neighbors.remove(nbr.getPrimaryAddr(), nbr); + this.electDR(); + } + + /** + * Elect a new DR on this ConnectPoint. + * + * @return the PIM Neighbor that wins + */ + public PIMNeighbor electDR() { + + for (PIMNeighbor nbr : this.neighbors.values()) { + if (this.designatedRouter == null) { + this.designatedRouter = nbr; + continue; + } + + if (nbr.getPriority() > this.designatedRouter.getPriority()) { + this.designatedRouter = nbr; + continue; + } + + // We could sort in ascending order + if (this.designatedRouter.getPrimaryAddr().compareTo(nbr.getPrimaryAddr()) > 0) { + this.designatedRouter = nbr; + continue; + } + } + + return this.designatedRouter; + } + + /** + * Elect a new DR given the new neighbor. + * + * @param nbr the new neighbor to use in DR election. + * @return the PIM Neighbor that wins DR election + */ + public PIMNeighbor electDR(PIMNeighbor nbr) { + + // Make sure I have + if (this.designatedRouter == null || + this.designatedRouter.getPriority() < nbr.getPriority() || + this.designatedRouter.getPrimaryAddr().compareTo(nbr.getPrimaryAddr()) > 0) { + this.designatedRouter = nbr; + } + return this.designatedRouter; + } + + /** + * Find or create a pim neighbor with a given ip address and connect point. + * + * @param ipaddr of the pim neighbor + * @param mac The mac address of our sending neighbor + * @return an existing or new PIM neighbor + */ + public PIMNeighbor findOrCreate(IpAddress ipaddr, MacAddress mac) { + PIMNeighbor nbr = this.findNeighbor(ipaddr); + if (nbr == null) { + nbr = new PIMNeighbor(ipaddr, mac, this); + this.addNeighbor(nbr); + this.electDR(nbr); + } + return nbr; + } + + /** + * Process a hello packet received on this Interface. + * + * @param ethPkt the ethernet packet containing the hello message + * @param cp the ConnectPoint of this interface + */ + public void processHello(Ethernet ethPkt, ConnectPoint cp) { + checkNotNull(ethPkt); + checkNotNull(cp); + + MacAddress srcmac = ethPkt.getSourceMAC(); + IPv4 ip = (IPv4) ethPkt.getPayload(); + Ip4Address srcip = Ip4Address.valueOf(ip.getSourceAddress()); + + PIM pim = (PIM) ip.getPayload(); + checkNotNull(pim); + + PIMHello hello = (PIMHello) pim.getPayload(); + checkNotNull(hello); + + PIMNeighbor nbr = this.findOrCreate(srcip, srcmac); + if (nbr == null) { + log.error("Could not create a neighbor for: {1}", srcip.toString()); + return; + } + + ConnectPoint icp = theInterface.connectPoint(); + checkNotNull(icp); + if (!cp.equals(icp)) { + log.error("PIM Hello message received from {} on incorrect interface {}", + nbr.getPrimaryAddr(), this.toString()); + return; + } + nbr.refresh(hello); + } + + /** + * Send a hello packet from this interface. + */ + public void sendHello() { + PIM pim = new PIM(); + PIMHello hello = new PIMHello(); + + // Create a PIM Hello + pim = new PIM(); + pim.setVersion((byte) 2); + pim.setPIMType((byte) PIM.TYPE_HELLO); + pim.setChecksum((short) 0); + + hello = new PIMHello(); + hello.createDefaultOptions(); + pim.setPayload(hello); + hello.setParent(pim); + + log.debug("Sending hello: \n"); + PIMPacketHandler.getInstance().sendPacket(pim, this); + } + + /** + * prints the connectPointNeighbors list with each neighbor list. + * + * @return string of neighbors. + */ + public String printNeighbors() { + String out = "PIM Neighbors Table: \n"; + for (PIMNeighbor nbr : this.neighbors.values()) { + out += "\t" + nbr.toString(); + } + return out; + } + + @Override + public String toString() { + IpAddress ipaddr = this.getIpAddress(); + String out = "PIM Neighbors: "; + if (ipaddr != null) { + out += "IP: " + ipaddr.toString(); + } else { + out += "IP: *Null*"; + } + out += "\tPR: " + String.valueOf(this.priority) + "\n"; + return out; + } + +} + |