Added the mcast-delete cli command and supporting class methods.
The changes also support withdrawing the associated intents.
Change-Id: I2d81d051c1bbbb5909175ec1544b45e4c208ba92
diff --git a/mfwd/src/main/java/org/onosproject/mfwd/cli/McastDeleteCommand.java b/mfwd/src/main/java/org/onosproject/mfwd/cli/McastDeleteCommand.java
new file mode 100644
index 0000000..ded5a1a
--- /dev/null
+++ b/mfwd/src/main/java/org/onosproject/mfwd/cli/McastDeleteCommand.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2014-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.mfwd.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+
+import org.onosproject.mfwd.impl.McastRouteTable;
+
+/**
+ * Delete a multicast route.
+ */
+@Command(scope = "onos", name = "mcast-delete",
+ description = "Delete a multicast route flow")
+public class McastDeleteCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "sAddr",
+ description = "IP Address of the multicast source. '*' can be used for any source (*, G) entry",
+ required = true, multiValued = false)
+ String sAddr = null;
+
+ @Argument(index = 1, name = "gAddr",
+ description = "IP Address of the multicast group",
+ required = true, multiValued = false)
+ String gAddr = null;
+
+ @Override
+ protected void execute() {
+ McastRouteTable mrib = McastRouteTable.getInstance();
+ mrib.removeRoute(sAddr, gAddr);
+ }
+}
+
diff --git a/mfwd/src/main/java/org/onosproject/mfwd/impl/McastForwarding.java b/mfwd/src/main/java/org/onosproject/mfwd/impl/McastForwarding.java
index 69b4dbd..68f3b45 100644
--- a/mfwd/src/main/java/org/onosproject/mfwd/impl/McastForwarding.java
+++ b/mfwd/src/main/java/org/onosproject/mfwd/impl/McastForwarding.java
@@ -185,6 +185,7 @@
return;
}
+ entry.setIntent();
McastIntentManager im = McastIntentManager.getInstance();
im.setIntent(entry);
diff --git a/mfwd/src/main/java/org/onosproject/mfwd/impl/McastIntentManager.java b/mfwd/src/main/java/org/onosproject/mfwd/impl/McastIntentManager.java
index 4a96eea..67a6045 100644
--- a/mfwd/src/main/java/org/onosproject/mfwd/impl/McastIntentManager.java
+++ b/mfwd/src/main/java/org/onosproject/mfwd/impl/McastIntentManager.java
@@ -22,7 +22,7 @@
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
-import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -54,6 +54,7 @@
*/
@Deactivate
public void deactivate() {
+ withdrawAllIntents();
}
/**
@@ -70,14 +71,15 @@
/**
* Install the PointToMultipoint forwarding intent.
* @param mroute multicast route entry
+ * @return the intent that has been set or null otherwise
*/
- public void setIntent(McastRoute mroute) {
+ public SinglePointToMultiPointIntent setIntent(McastRoute mroute) {
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
if (mroute.getIngressPoint() == null ||
mroute.getEgressPoints().isEmpty()) {
- return;
+ return null;
}
/*
@@ -102,14 +104,27 @@
build();
intentService.submit(intent);
- mroute.setIntent(intent);
+ return intent;
}
/**
- * Withdraw the intent from the network.
- * @param mroute the multicast route representing the intent
+ * Withdraw the intent represented by this route.
+ * @param mroute the mcast route whose intent we want to remove
*/
- public void withdrawIntent(McastRoute mroute) {
- Key key = mroute.getIntentKey();
+ public void withdrawIntent(McastRouteBase mroute) {
+ Intent intent = intentService.getIntent(mroute.getIntentKey());
+ intentService.withdraw(intent);
+ }
+
+ /**
+ * Withdraw all intents.
+ *
+ * This will be called from the deactivate method so we don't leave
+ * a mess behind us after we leave.
+ */
+ public void withdrawAllIntents() {
+ for (Intent intent : intentService.getIntents()) {
+ intentService.withdraw(intent);
+ }
}
}
diff --git a/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRoute.java b/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRoute.java
index e499454..397ce35 100644
--- a/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRoute.java
+++ b/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRoute.java
@@ -18,7 +18,6 @@
import org.onlab.packet.IpPrefix;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.intent.Key;
-import org.onosproject.net.intent.SinglePointToMultiPointIntent;
import java.util.Set;
@@ -87,10 +86,15 @@
public Set<ConnectPoint> getEgressPoints();
/**
- * Set the Intent key.
- * @param intent intent
+ * Have the McastIntentManager create an intent, attempt to
+ * install the intent and then save the key.
*/
- public void setIntent(SinglePointToMultiPointIntent intent);
+ public void setIntent();
+
+ /**
+ * Withdraw the intent if it has been installed.
+ */
+ public void withdrawIntent();
/**
* Get the intent key.
diff --git a/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRouteBase.java b/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRouteBase.java
index 2c00268..d6b86b8 100644
--- a/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRouteBase.java
+++ b/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRouteBase.java
@@ -216,6 +216,35 @@
}
/**
+ * Have the McastIntentManager create and set the intent, then save the intent key.
+ *
+ * If we already have an intent, we will first withdraw the existing intent and
+ * replace it with a new one. This will support the case where the ingress connectPoint
+ * or group of egress connectPoints change.
+ */
+ public void setIntent() {
+ if (this.intentKey != null) {
+ this.withdrawIntent();
+ }
+ McastIntentManager im = McastIntentManager.getInstance();
+ SinglePointToMultiPointIntent intent = im.setIntent(this);
+ this.intentKey = intent.key();
+ }
+
+ /**
+ * Withdraw the intent and set the key to null.
+ */
+ public void withdrawIntent() {
+ if (intentKey == null) {
+ // nothing to withdraw
+ return;
+ }
+ McastIntentManager im = McastIntentManager.getInstance();
+ im.withdrawIntent(this);
+ this.intentKey = null;
+ }
+
+ /**
* Pretty Print this Multicast Route. Works for McastRouteSource and McastRouteGroup.
* @return pretty string of the multicast route
*/
diff --git a/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRouteGroup.java b/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRouteGroup.java
index ccf6472..2159093 100644
--- a/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRouteGroup.java
+++ b/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRouteGroup.java
@@ -56,16 +56,6 @@
}
/**
- * Add a new McastRouteSource to this group.
- *
- * @param src the multicast source
- */
- public void addSource(McastRouteSource src) {
- checkNotNull(src);
- this.sources.put(src.getSaddr(), src);
- }
-
- /**
* Find a specific multicast source address for this group.
* @param saddr the source address
* @return the multicast source route or null if it does not exist
@@ -81,4 +71,36 @@
public HashMap<IpPrefix, McastRouteSource> getSources() {
return this.sources;
}
+
+ /**
+ * Add a new McastRouteSource to this group.
+ *
+ * @param src the multicast source
+ */
+ public void addSource(McastRouteSource src) {
+ checkNotNull(src);
+ this.sources.put(src.getSaddr(), src);
+ }
+
+ /**
+ * Remove the source with this specific IpPrefix from this group entry.
+ * @param spfx IP Prefix of the source to be removed
+ * @return the source route that was just removed
+ */
+ public McastRouteSource removeSource(IpPrefix spfx) {
+ McastRouteSource src = this.sources.remove(spfx);
+ src.withdrawIntent();
+ return src;
+ }
+
+ /**
+ * Remove all sources from this.
+ */
+ public void removeSources() {
+ for (McastRouteSource src : this.sources.values()) {
+ src.withdrawIntent();
+ this.sources.remove(src.getSaddr());
+ }
+ }
+
}
diff --git a/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRouteTable.java b/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRouteTable.java
index 9ef7f7a..bb3cced 100644
--- a/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRouteTable.java
+++ b/mfwd/src/main/java/org/onosproject/mfwd/impl/McastRouteTable.java
@@ -89,7 +89,7 @@
*
* @param group The McastRouteGroup to save
*/
- private void storeMcastGroup(McastRouteGroup group) {
+ private void storeGroup(McastRouteGroup group) {
if (group.isIp4()) {
mrib4.put(group.getGaddr(), group);
} else {
@@ -100,12 +100,21 @@
}
/**
+ * remove the group.
+ * @param group the group to be removed
*/
+ private void removeGroup(McastRouteGroup group) {
+ IpPrefix gpfx = group.getGaddr();
+ if (gpfx.isIp4()) {
+ mrib4.remove(gpfx);
+ } else if (ipv6Enabled) {
+ mrib6.remove(gpfx);
+ }
+ }
+
/**
* Add a multicast route to the MRIB. This function will.
*
- * TODO: check the addresses to determine if the have a /mask if not add one.
- *
* @param saddr source address * or x.x.x.x or x.x.x.x/y
* @param gaddr group address x.x.x.x or x.x.x.x/y
* @return the multicast route
@@ -152,6 +161,7 @@
}
}
}
+
/**
* If the source prefix length is 0 then we have our (*, g) entry, we can
* just return now.
@@ -182,17 +192,60 @@
}
/**
- * Save the multicast group in the multicast route table.
- * @param group the group address
+ * Delete a multicast route from the MRIB.
+ *
+ * @param saddr source address * or x.x.x.x or x.x.x.x/y
+ * @param gaddr group address x.x.x.x or x.x.x.x/y
*/
- private void storeGroup(McastRouteGroup group) {
- if (group.isIp4()) {
- mrib4.put(group.getGaddr(), group);
- } else {
+ public void removeRoute(String saddr, String gaddr) {
+ IpPrefix gpfx = IpPrefix.valueOf(gaddr);
+ IpPrefix spfx = IpPrefix.valueOf(0, 0);
+ if (saddr != null && !saddr.equals("*")) {
+ spfx = IpPrefix.valueOf(saddr);
+ }
+ removeRoute(spfx, gpfx);
+ }
- if (ipv6Enabled) {
- mrib6.put(group.getGaddr(), group);
+ /**
+ * Remove a multicast route.
+ *
+ * @param spfx the source prefix
+ * @param gpfx the group prefix
+ */
+ public void removeRoute(IpPrefix spfx, IpPrefix gpfx) {
+
+ /**
+ * If a group route (*, g) does not exist we will need to make so we
+ * can start attaching our sources to the group entry.
+ */
+ McastRouteGroup group = findMcastGroup(gpfx);
+ if (group == null) {
+ // The group does not exist, we can't remove it.
+ return;
+ }
+
+ /**
+ * If the source prefix length is 0 then we have a (*, g) entry, which
+ * means we will remove this group and all of it's sources. We will
+ * also withdraw it's intent if need be.
+ */
+ if (spfx.prefixLength() > 0) {
+ group.removeSource(spfx);
+
+ /*
+ * Now a little house keeping. If this group has no more sources
+ * nor egress connectPoints git rid of it.
+ */
+ if (group.getSources().size() == 0 &&
+ group.getEgressPoints().size() == 0) {
+ removeGroup(group);
}
+
+ } else {
+ // Group remove has been explicitly requested.
+ group.removeSources();
+ group.withdrawIntent();
+ removeGroup(group);
}
}
diff --git a/mfwd/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/mfwd/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 4048f36..966cb4f 100644
--- a/mfwd/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/mfwd/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -20,6 +20,9 @@
<action class="org.onosproject.mfwd.cli.McastJoinCommand"/>
</command>
<command>
+ <action class="org.onosproject.mfwd.cli.McastDeleteCommand"/>
+ </command>
+ <command>
<action class="org.onosproject.mfwd.cli.McastShowCommand"/>
</command>
</command-bundle>