diff options
Diffstat (limited to 'framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java')
-rw-r--r-- | framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java new file mode 100644 index 00000000..1a96138f --- /dev/null +++ b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java @@ -0,0 +1,340 @@ +/* + * Copyright 2014-2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in reliance 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.jboss.netty.util.Timeout; +import org.jboss.netty.util.TimerTask; +import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; +import org.onlab.packet.pim.PIMHello; +import org.onlab.packet.pim.PIMHelloOption; +import org.onosproject.net.ConnectPoint; +import org.slf4j.Logger; + +import java.nio.ByteBuffer; +import java.util.concurrent.TimeUnit; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * PIMNeighbor represents all the PIM routers that have sent us + * hello messages, or that possibly have been statically configured. + */ +public class PIMNeighbor { + private final Logger log = getLogger(getClass()); + + // The primary address of this PIM neighbor + private IpAddress primaryAddr; + + // The MacAddress of this neighbor + private MacAddress macAddress; + + // The ConnectPoint this PIM neighbor is connected to. + private ConnectPoint connectPoint; + + // Is this neighbor us? + private boolean isThisUs = false; + + // The option values this neighbor has sent us. + private int priority = 0; + private int genId = 0; + private short holdtime = 0; + + // Is this pim neighbor the DR? + private boolean isDr = false; + + // Timeout for this neighbor + private volatile Timeout timeout; + + private boolean reelect = false; + + // A back pointer the neighbors list this neighbor belongs to. + private PIMNeighbors neighbors; + + /** + * Construct this neighbor from the address and connect point. + * + * @param ipaddr IP Address of neighbor + * @param macaddr MAC Address of the neighbor + * @param cp The ConnectPoint of this neighbor + */ + public PIMNeighbor(IpAddress ipaddr, MacAddress macaddr, ConnectPoint cp) { + this.macAddress = macaddr; + this.primaryAddr = ipaddr; + this.connectPoint = cp; + this.resetTimeout(); + } + + /** + * Get the primary address of this neighbor. + * + * @return the primary IP address. + */ + public IpAddress getPrimaryAddr() { + return primaryAddr; + } + + /** + * Set the primary address of this neighbor. + * + * @param primaryAddr the address we'll use when sending hello messages + */ + public void setPrimaryAddr(IpAddress primaryAddr) { + this.primaryAddr = primaryAddr; + } + + /** + * Get the priority this neighbor has advertised to us. + * + * @return the priority + */ + public int getPriority() { + return priority; + } + + /** + * Set the priority for this neighbor. + * + * @param priority This neighbors priority. + */ + public void setPriority(int priority) { + this.priority = priority; + } + + /** + * Get the generation ID. + * + * @return the generation ID. + */ + public int getGenId() { + return genId; + } + + /** + * Set the generation ID. + * + * @param genId the generation ID. + */ + public void setGenId(int genId) { + this.genId = genId; + } + + /** + * Get the holdtime for this neighbor. + * + * @return the holdtime + */ + public short getHoldtime() { + return holdtime; + } + + /** + * Set the holdtime for this neighbor. + * + * @param holdtime the holdtime. + */ + public void setholdtime(short holdtime) { + this.holdtime = holdtime; + } + + /** + * Is this neighbor the designated router on this connect point? + * + * @return true if so, false if not. + */ + public boolean isDr() { + return isDr; + } + + /** + * Set this router as the designated router on this connect point. + * + * @param isDr True is this neighbor is the DR false otherwise + */ + public void setIsDr(boolean isDr) { + this.isDr = isDr; + } + + /** + * The ConnectPoint this neighbor is connected to. + * + * @return the ConnectPoint + */ + public ConnectPoint getConnectPoint() { + return connectPoint; + } + + /** + * Set the ConnectPoint this router is connected to. + * + * @param connectPoint the ConnectPoint this router is connected to. + */ + public void setConnectPoint(ConnectPoint connectPoint) { + this.connectPoint = connectPoint; + } + + /** + * Set a back pointer to the neighbors list this neighbor is a member of. + * + * @param neighbors the neighbor list this neighbor belongs to + */ + public void setNeighbors(PIMNeighbors neighbors) { + this.neighbors = neighbors; + } + + /** + * We have received a fresh hello from a neighbor, now we need to process it. + * Depending on the values received in the the hello options may force a + * re-election process. + * + * We will also refresh the timeout for this neighbor. + * + * @param hello copy of the hello we'll be able to extract options from. + */ + public void refresh(PIMHello hello) { + checkNotNull(hello); + + for (PIMHelloOption opt : hello.getOptions().values()) { + + int len = opt.getOptLength(); + byte [] value = new byte[len]; + ByteBuffer bb = ByteBuffer.wrap(value); + + switch (opt.getOptType()) { + case PIMHelloOption.OPT_GENID: + int newid = bb.getInt(); + if (this.genId != newid) { + // TODO: we have a newly rebooted neighbor. Send them our joins. + this.genId = newid; + } + break; + + case PIMHelloOption.OPT_PRIORITY: + int newpri = bb.getInt(); + if (this.priority != newpri) { + + // The priorities have changed. We may need to re-elect a new DR? + if (this.isDr || this.neighbors.getDesignatedRouter().getPriority() < priority) { + reelect = true; + } + this.priority = newpri; + } + break; + + case PIMHelloOption.OPT_HOLDTIME: + short holdtime = bb.getShort(); + if (this.holdtime != holdtime) { + this.holdtime = holdtime; + if (holdtime == 0) { + // We have a neighbor going down. We can remove all joins + // we have learned from them. + // TODO: What else do we need to do when a neighbor goes down? + + log.debug("PIM Neighbor has timed out: {}", this.primaryAddr.toString()); + return; + } + } + break; + + case PIMHelloOption.OPT_PRUNEDELAY: + case PIMHelloOption.OPT_ADDRLIST: + // TODO: implement prune delay and addr list. Fall through for now. + + default: + log.debug("PIM Hello option type: {} not yet supported or unknown.", opt.getOptType()); + break; + } + } + + if (reelect) { + this.neighbors.electDR(this); + } + + // Reset the next timeout timer + this.resetTimeout(); + } + + /* --------------------------------------- Timer functions -------------------------- */ + + /** + * Restart the timeout task for this neighbor. + */ + private void resetTimeout() { + + if (this.holdtime == 0) { + + // Prepare to die. + log.debug("shutting down timer for nbr {}", this.primaryAddr.toString()); + if (this.timeout != null) { + this.timeout.cancel(); + this.timeout = null; + } + return; + } + + // Cancel the existing timeout and start a fresh new one. + if (this.timeout != null) { + this.timeout.cancel(); + } + + this.timeout = PIMTimer.getTimer().newTimeout(new NeighborTimeoutTask(this), holdtime, TimeUnit.SECONDS); + } + + /** + * The task to run when a neighbor timeout expires. + */ + private final class NeighborTimeoutTask implements TimerTask { + PIMNeighbor nbr; + + NeighborTimeoutTask(PIMNeighbor nbr) { + this.nbr = nbr; + } + + @Override + public void run(Timeout timeout) throws Exception { + + // TODO: log.debug; + PIMNeighbors neighbors = nbr.neighbors; + neighbors.removeNeighbor(nbr.getPrimaryAddr()); + } + } + + /** + * Stop the timeout timer. + * + * This happens when we remove the neighbor. + */ + private final void stopTimeout() { + this.timeout.cancel(); + this.timeout = null; + } + + @Override + public String toString() { + String out = ""; + if (this.isDr) { + out += "*NBR:"; + } else { + out += "NBR:"; + } + out += "\tIP: " + this.primaryAddr.toString(); + out += "\tPr: " + String.valueOf(this.priority); + out += "\tHoldTime: " + String.valueOf(this.holdtime); + out += "\tGenID: " + String.valueOf(this.genId) + "\n"; + return out; + } +}
\ No newline at end of file |