aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMJoinPrune.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMJoinPrune.java')
-rw-r--r--framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMJoinPrune.java271
1 files changed, 271 insertions, 0 deletions
diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMJoinPrune.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMJoinPrune.java
new file mode 100644
index 00000000..9653115b
--- /dev/null
+++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/pim/PIMJoinPrune.java
@@ -0,0 +1,271 @@
+/*
+ * 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.onlab.packet.pim;
+
+import org.onlab.packet.BasePacket;
+import org.onlab.packet.Deserializer;
+import org.onlab.packet.IPacket;
+import org.onlab.packet.IpPrefix;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+
+import static org.onlab.packet.PacketUtils.checkInput;
+
+public class PIMJoinPrune extends BasePacket {
+
+ private PIMAddrUnicast upstreamAddr = new PIMAddrUnicast();
+ private short holdTime = (short) 0xffff;
+
+ private class JoinPruneGroup {
+ protected IpPrefix group;
+ protected HashMap<IpPrefix, IpPrefix> joins = new HashMap<>();
+ protected HashMap<IpPrefix, IpPrefix> prunes = new HashMap<>();
+
+ public JoinPruneGroup(IpPrefix grp) {
+ group = grp;
+ }
+ }
+ private HashMap<IpPrefix, JoinPruneGroup> joinPrunes = new HashMap<>();
+
+ /**
+ * Get the J/P hold time.
+ *
+ * @return specified in seconds.
+ */
+ public short getHoldTime() {
+ return holdTime;
+ }
+
+ /**
+ * Set the J/P holdtime in seconds.
+ *
+ * @param holdTime return the holdtime.
+ */
+ public void setHoldTime(short holdTime) {
+ this.holdTime = holdTime;
+ }
+
+ /**
+ * Get the upstreamAddr for this J/P request.
+ *
+ * @return the upstream address.
+ */
+ public PIMAddrUnicast getUpstreamAddr() {
+ return upstreamAddr;
+ }
+
+ /**
+ * Set the upstream address of this PIM J/P request.
+ *
+ * @param upstr the PIM Upstream unicast address
+ */
+ public void setUpstreamAddr(PIMAddrUnicast upstr) {
+ this.upstreamAddr = upstr;
+ }
+
+ /**
+ * Add the specified s,g to join field.
+ *
+ * @param saddr the source address of the route
+ * @param gaddr the group address of the route
+ * @param join true for a join, false for a prune.
+ */
+ public void addJoinPrune(String saddr, String gaddr, boolean join) {
+ IpPrefix gpfx = IpPrefix.valueOf(gaddr);
+ IpPrefix spfx = IpPrefix.valueOf(saddr);
+ addJoinPrune(spfx, gpfx, join);
+ }
+
+ /**
+ * Add the specified S, G to the join field.
+ *
+ * @param spfx the source prefix of the route
+ * @param gpfx the group prefix of the route
+ * @param join true for join, false for prune
+ */
+ public void addJoinPrune(IpPrefix spfx, IpPrefix gpfx, boolean join) {
+ JoinPruneGroup jpg = joinPrunes.get(gpfx);
+ if (jpg == null) {
+ jpg = new JoinPruneGroup(gpfx);
+ joinPrunes.put(gpfx, jpg);
+ }
+
+ HashMap<IpPrefix, IpPrefix> members = (join) ? jpg.joins : jpg.prunes;
+ if (members.get(spfx) == null) {
+ members.put(spfx, spfx);
+ }
+ }
+
+ /**
+ * Add a join given strings represending the source and group addresses.
+ *
+ * @param saddr source address
+ * @param gaddr group address
+ */
+ public void addJoin(String saddr, String gaddr) {
+ this.addJoinPrune(saddr, gaddr, true);
+ }
+
+ /**
+ * Add a prune given strings represending the source and group addresses.
+ *
+ * @param saddr source address
+ * @param gaddr group address
+ */
+ public void addPrune(String saddr, String gaddr) {
+ this.addJoinPrune(saddr, gaddr, false);
+ }
+
+ /**
+ * Sets all payloads parent packet if applicable, then serializes this
+ * packet and all payloads.
+ *
+ * @return a byte[] containing this packet and payloads
+ */
+ @Override
+ public byte[] serialize() {
+
+ byte[] data = new byte[8096]; // Come up with something better
+ ByteBuffer bb = ByteBuffer.wrap(data);
+
+ bb.put(upstreamAddr.serialize());
+ bb.put((byte) 0); // reserved
+
+ int ngrps = joinPrunes.size();
+ bb.put((byte) ngrps);
+ bb.putShort(this.holdTime);
+
+ // Walk the group list and input all groups
+ for (JoinPruneGroup jpg : joinPrunes.values()) {
+ PIMAddrGroup grp = new PIMAddrGroup(jpg.group);
+ bb.put(grp.serialize());
+
+ // put the number of joins and prunes
+ bb.putShort((short) jpg.joins.size());
+ bb.putShort((short) jpg.prunes.size());
+
+ // Set all of the joins
+ for (IpPrefix spfx : jpg.joins.values()) {
+ PIMAddrSource src = new PIMAddrSource(spfx);
+ bb.put(src.serialize());
+ }
+
+ // Set all of the prunes
+ for (IpPrefix spfx : jpg.prunes.values()) {
+ PIMAddrSource src = new PIMAddrSource(spfx);
+ bb.put(src.serialize());
+ }
+ }
+
+ int len = bb.position();
+ byte[] data2 = new byte[len];
+ bb = ByteBuffer.wrap(data2, 0, len);
+ bb.put(data, 0, len);
+ return data2;
+ }
+
+ // TODO: I suppose I really need to implement this?
+ @Override
+ public IPacket deserialize(final byte[] data, final int offset,
+ final int length) {
+ final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+ return this;
+ }
+
+ /**
+ * Return the J/P deserializer function.
+ *
+ * @return a function that will deserialize a J/P message.
+ */
+ public static Deserializer<PIMJoinPrune> deserializer() {
+ return (data, offset, length) -> {
+
+ /*
+ * Delay buffer checks until we read enough of the packet to know how
+ * much data we will require. Each encoded address deserializer function
+ * will ensure there is enough data for that address.
+ */
+ PIMJoinPrune jp = new PIMJoinPrune();
+ final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
+
+ // We must get a PIM encoded unicast address
+ PIMAddrUnicast upstream = new PIMAddrUnicast();
+ upstream.deserialize(bb);
+ jp.setUpstreamAddr(upstream);
+
+ // Use this boolean to determine the buffer space we need according to address sizes
+ boolean ipv4 = upstream.getAddr().isIp4();
+
+ // We need at minimum 4 bytes for reserved(1), ngroups(1) & holdtime(2)
+ checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), 4);
+
+ // get and skip the reserved byte
+ bb.get();
+
+ // Get the number of groups.
+ int ngroups = bb.get();
+
+ // Save the holdtime.
+ jp.setHoldTime(bb.getShort());
+
+
+ for (int i = 0; i < ngroups; i++) {
+ PIMAddrGroup grp = new PIMAddrGroup();
+
+ /*
+ * grp.deserialize will ensure the buffer has enough data to read the group address.
+ */
+ grp.deserialize(bb);
+
+ checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), 4);
+ int njoins = bb.getShort();
+ int nprunes = bb.getShort();
+
+ /*
+ * Now we'll verify we have enough buffer to read the next
+ * group of join and prune addresses for this group.
+ */
+ int required = (njoins + nprunes) *
+ (ipv4 ? PIMAddrSource.ENC_SOURCE_IPV4_BYTE_LENGTH : PIMAddrSource.ENC_SOURCE_IPV6_BYTE_LENGTH);
+ checkInput(bb.array(), bb.position(), bb.limit() - bb.position(), required);
+
+ // Now iterate through the joins for this group
+ for (; njoins > 0; njoins--) {
+
+ PIMAddrSource src = new PIMAddrSource();
+ src.deserialize(bb);
+
+ jp.addJoinPrune(
+ src.getAddr().toIpPrefix(),
+ grp.getAddr().toIpPrefix(), true);
+ }
+
+ // Now iterate through the prunes for this group
+ for (; nprunes > 0; nprunes--) {
+
+ PIMAddrSource src = new PIMAddrSource();
+ src.deserialize(bb);
+ jp.addJoinPrune(
+ src.getAddr().toIpPrefix(),
+ grp.getAddr().toIpPrefix(), false);
+ }
+ }
+
+ return jp;
+ };
+ }
+}