Added PIM neighbors
Change-Id: Ibce9741be02b9e79e53780adc2ce272698a70ee6
diff --git a/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java b/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java
index 8bf2333..f54b7b2 100644
--- a/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java
+++ b/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java
@@ -26,8 +26,11 @@
import org.onosproject.net.host.InterfaceIpAddress;
import org.slf4j.Logger;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
+import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -52,6 +55,12 @@
// Our current genid
private int genid = PIMHelloOption.DEFAULT_GENID; // Needs to be assigned.
+ // The IP address of the DR
+ IpAddress drIpaddress;
+
+ // A map of all our PIM neighbors keyed on our neighbors IP address
+ private Map<IpAddress, PIMNeighbor> pimNeighbors = new HashMap<>();
+
/**
* Create a PIMInterface from an ONOS Interface.
*
@@ -59,6 +68,17 @@
*/
public PIMInterface(Interface intf) {
onosInterface = intf;
+ IpAddress ourIp = getIpAddress();
+ MacAddress mac = intf.mac();
+
+ // Create a PIM Neighbor to represent ourselves for DR election.
+ PIMNeighbor us = new PIMNeighbor(ourIp, mac);
+
+ // Priority and IP address are all we need to DR election.
+ us.setPriority(priority);
+
+ pimNeighbors.put(ourIp, us);
+ drIpaddress = ourIp;
}
/**
@@ -67,7 +87,8 @@
* @return ONOS Interface.
*/
public Interface getInterface() {
- return this.onosInterface;
+ return onosInterface;
+
}
/**
@@ -76,7 +97,7 @@
* @param intf ONOS Interface.
*/
public PIMInterface setInterface(Interface intf) {
- this.onosInterface = intf;
+ onosInterface = intf;
return this;
}
@@ -86,7 +107,7 @@
* @return a set of Ip Addresses on this interface
*/
public Set<InterfaceIpAddress> getIpAddresses() {
- return this.onosInterface.ipAddresses();
+ return onosInterface.ipAddresses();
}
/**
@@ -113,7 +134,7 @@
* @return the holdtime
*/
public short getHoldtime() {
- return this.holdtime;
+ return holdtime;
}
/**
@@ -122,7 +143,7 @@
* @return The prune delay
*/
public int getPruneDelay() {
- return this.pruneDelay;
+ return pruneDelay;
}
/**
@@ -131,7 +152,7 @@
* @return our priority
*/
public int getPriority() {
- return this.priority;
+ return priority;
}
/**
@@ -140,11 +161,18 @@
* @return our generation ID
*/
public int getGenid() {
- return this.genid;
+ return genid;
}
/**
- * Process an incoming PIM Hello message.
+ * Process an incoming PIM Hello message. There are a few things going on in
+ * this method:
+ * <ul>
+ * <li>We <em>may</em> have to create a new neighbor if one does not already exist</li>
+ * <li>We <em>may</em> need to re-elect a new DR if new information is received</li>
+ * <li>We <em>may</em> need to send an existing neighbor all joins if the genid changed</li>
+ * <li>We will refresh the neighbors timestamp</li>
+ * </ul>
*
* @param ethPkt the Ethernet packet header
*/
@@ -163,32 +191,69 @@
return;
}
- // TODO: Maybe a good idea to check the checksum. Let's jump into the hello options.
+ // get the DR values for later calculation
+ PIMNeighbor dr = pimNeighbors.get(drIpaddress);
+ checkNotNull(dr);
+
+ IpAddress drip = drIpaddress;
+ int drpri = dr.getPriority();
+
+ // Assume we do not need to run a DR election
+ boolean reElectDr = false;
+ boolean genidChanged = false;
+
PIMHello hello = (PIMHello) pimhdr.getPayload();
- // TODO: this is about where we find or create our PIMNeighbor
-
- boolean reElectDr = false;
-
- // Start walking through all the hello options to handle accordingly.
- for (PIMHelloOption opt : hello.getOptions().values()) {
-
- // TODO: This is where we handle the options and modify the neighbor accordingly.
- // We'll need to create the PIMNeighbor class next. Depending on what happens
- // we may need to re-elect a DR
+ // Determine if we already have a PIMNeighbor
+ PIMNeighbor nbr = pimNeighbors.getOrDefault(srcip, null);
+ if (nbr == null) {
+ nbr = new PIMNeighbor(srcip, hello.getOptions());
+ checkNotNull(nbr);
+ } else {
+ Integer previousGenid = nbr.getGenid();
+ nbr.addOptions(hello.getOptions());
+ if (previousGenid != nbr.getGenid()) {
+ genidChanged = true;
+ }
}
- if (reElectDr) {
- // TODO: create an election() method and call it here with a PIMNeighbor
+ // Refresh this neighbors timestamp
+ nbr.refreshTimestamp();
+
+ /*
+ * the election method will frist determine if an election
+ * needs to be run, if so it will run the election. The
+ * IP address of the DR will be returned. If the IP address
+ * of the DR is different from what we already have we know a
+ * new DR has been elected.
+ */
+ IpAddress electedIp = election(nbr, drip, drpri);
+ if (!drip.equals(electedIp)) {
+ // we have a new DR.
+ drIpaddress = electedIp;
}
}
+ // Run an election if we need to. Return the elected IP address.
+ private IpAddress election(PIMNeighbor nbr, IpAddress drip, int drpri) {
+
+ IpAddress nbrip = nbr.getIpaddr();
+ if (nbr.getPriority() > drpri) {
+ return nbrip;
+ }
+
+ if (nbrip.compareTo(drip) > 0) {
+ return nbrip;
+ }
+ return drip;
+ }
+
/**
* Process an incoming PIM JoinPrune message.
*
* @param ethPkt the Ethernet packet header.
*/
public void processJoinPrune(Ethernet ethPkt) {
-
+ // TODO: add Join/Prune processing code.
}
}
diff --git a/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java b/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java
new file mode 100644
index 0000000..a1f9eec
--- /dev/null
+++ b/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java
@@ -0,0 +1,228 @@
+/*
+ * 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.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.pim.PIMHelloOption;
+import org.slf4j.Logger;
+
+import java.nio.ByteBuffer;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Map;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+public class PIMNeighbor {
+
+ private final Logger log = getLogger(getClass());
+
+ // IP Address of this neighbor
+ private IpAddress ipAddr;
+
+ // MAC Address of the neighbor (Need for sending J/P)
+ private MacAddress macAddr;
+
+ // Hello Options
+ // Our hello opt holdTime
+ private short holdTime;
+
+ // Our hello opt prune delay
+ private int pruneDelay;
+
+ // Neighbor priority
+ private int priority;
+
+ // Our current genId
+ private int genId;
+
+ // Our timestamp for this neighbor
+ private Date lastRefresh;
+
+ /**
+ * Construct a new PIM Neighbor.
+ *
+ * @param ipAddr the IP Address of our new neighbor
+ */
+ public PIMNeighbor(IpAddress ipAddr, Map<Short, PIMHelloOption> opts) {
+ this.ipAddr = ipAddr;
+ this.addOptions(opts);
+ }
+
+ /**
+ * Construct a new PIM neighbor.
+ *
+ * @param ipAddr the neighbors IP addr
+ */
+ public PIMNeighbor(IpAddress ipAddr, MacAddress macAddr) {
+ this.ipAddr = ipAddr;
+ this.macAddr = macAddr;
+ }
+
+ /**
+ * Get the MAC address of this neighbor.
+ *
+ * @return the mac address
+ */
+ public MacAddress getMacaddr() {
+ return macAddr;
+ }
+
+ /**
+ * Get the IP Address of our neighbor.
+ *
+ * @return the IP address of our neighbor
+ */
+ public IpAddress getIpaddr() {
+ return ipAddr;
+ }
+
+ /**
+ * Set the IP address of our neighbor.
+ *
+ * @param ipAddr our neighbors IP address
+ */
+ public void setIpaddr(IpAddress ipAddr) {
+ this.ipAddr = ipAddr;
+ }
+
+ /**
+ * Get our neighbors holdTime.
+ *
+ * @return the holdTime
+ */
+ public short getHoldtime() {
+ return holdTime;
+ }
+
+ /**
+ * Set our neighbors holdTime.
+ *
+ * @param holdTime the holdTime
+ */
+ public void setHoldtime(short holdTime) {
+ this.holdTime = holdTime;
+ }
+
+ /**
+ * Get our neighbors prune delay.
+ *
+ * @return our neighbors prune delay
+ */
+ public int getPruneDelay() {
+ return pruneDelay;
+ }
+
+ /**
+ * Set our neighbors prune delay.
+ *
+ * @param pruneDelay the prune delay
+ */
+ public void setPruneDelay(int pruneDelay) {
+ this.pruneDelay = pruneDelay;
+ }
+
+ /**
+ * Get our neighbors priority.
+ *
+ * @return our neighbors priority
+ */
+ public int getPriority() {
+ return priority;
+ }
+
+ /**
+ * Set our neighbors priority.
+ *
+ * @param priority our neighbors priority
+ */
+ public void setPriority(int priority) {
+ this.priority = priority;
+ }
+
+ /**
+ * Get our neighbors Genid.
+ *
+ * @return our neighbor Genid
+ */
+ public int getGenid() {
+ return genId;
+ }
+
+ /**
+ * Set our neighbors GenId.
+ *
+ * @param genId our neighbors GenId
+ */
+ public void setGenid(int genId) {
+ this.genId = genId;
+ }
+
+ /**
+ * Add the options for this neighbor if needed.
+ *
+ * @param opts the options to be added/modified
+ * @return true if options changed, false if no option has changed
+ */
+ public boolean addOptions(Map<Short, PIMHelloOption> opts) {
+
+ boolean changed = false;
+
+ for (PIMHelloOption opt : opts.values()) {
+ Short otype = opt.getOptType();
+ ByteBuffer val = ByteBuffer.wrap(opt.getValue());
+
+ if (otype == PIMHelloOption.OPT_ADDRLIST) {
+ // TODO: Will implement someday
+ } else if (otype == PIMHelloOption.OPT_GENID) {
+ int newval = val.getInt();
+ if (newval != genId) {
+ genId = newval;
+ changed = true;
+ }
+ } else if (otype == PIMHelloOption.OPT_HOLDTIME) {
+ short newval = val.getShort();
+ if (newval != holdTime) {
+ holdTime = newval;
+ changed = true;
+ }
+ } else if (otype == PIMHelloOption.OPT_PRIORITY) {
+ int newval = val.getInt();
+ if (newval != priority) {
+ priority = newval;
+ changed = true;
+ }
+ } else if (otype == PIMHelloOption.OPT_PRUNEDELAY) {
+ int newval = val.getInt();
+ if (newval != pruneDelay) {
+ pruneDelay = newval;
+ changed = true;
+ }
+ } else {
+ log.warn("received unknown pim hello options" + otype);
+ }
+ }
+ return changed;
+ }
+
+ /**
+ * Refresh this neighbors timestamp.
+ */
+ public void refreshTimestamp() {
+ lastRefresh = Calendar.getInstance().getTime();
+ }
+}