[CORD-2903] Improve SR/Multicast APIs
Change-Id: Id44af87569e0a83129c96504b21c69e1d455f785
(cherry picked from commit a2858a34a26e02e9d2dd66dc562d0f6fb2c4bdd1)
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index eff78e5..c200d74 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -675,6 +675,12 @@
}
@Override
+ public Multimap<ConnectPoint, List<ConnectPoint>> getMcastTrees(IpAddress mcastIp,
+ ConnectPoint sourcecp) {
+ return mcastHandler.getMcastTrees(mcastIp, sourcecp);
+ }
+
+ @Override
public Map<IpAddress, NodeId> getMcastLeaders(IpAddress mcastIp) {
return mcastHandler.getMcastLeaders(mcastIp);
}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
index aabed47..87ba7f3 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
@@ -15,6 +15,7 @@
*/
package org.onosproject.segmentrouting;
+import com.google.common.collect.Multimap;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onosproject.cluster.NodeId;
@@ -237,7 +238,10 @@
*
* @param mcastIp the group ip
* @return the mapping mcastIp-device to mcast role
+ *
+ * @deprecated in 1.12 ("Magpie") release.
*/
+ @Deprecated
Map<McastStoreKey, McastRole> getMcastRoles(IpAddress mcastIp);
/**
@@ -245,9 +249,23 @@
*
* @param mcastIp the group ip
* @return the mapping egress point to mcast path
+ *
+ * @deprecated in 1.12 ("Magpie") release.
*/
+ @Deprecated
Map<ConnectPoint, List<ConnectPoint>> getMcastPaths(IpAddress mcastIp);
+
+ /**
+ * Returns the associated trees to the mcast group.
+ *
+ * @param mcastIp the group ip
+ * @param sourcecp the source connect point
+ * @return the mapping egress point to mcast path
+ */
+ Multimap<ConnectPoint, List<ConnectPoint>> getMcastTrees(IpAddress mcastIp,
+ ConnectPoint sourcecp);
+
/**
* Return the leaders of the mcast groups.
*
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastNextListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastNextListCommand.java
index a713130..e5d8b12 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastNextListCommand.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastNextListCommand.java
@@ -57,7 +57,6 @@
IpAddress mcastGroup = null;
if (!isNullOrEmpty(gAddr)) {
mcastGroup = IpAddress.valueOf(gAddr);
-
}
// Get SR service
SegmentRoutingService srService = get(SegmentRoutingService.class);
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastTreeListCommand.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastTreeListCommand.java
index d1de73c..a1ee1f2 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastTreeListCommand.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/cli/McastTreeListCommand.java
@@ -16,7 +16,10 @@
package org.onosproject.segmentrouting.cli;
-import com.google.common.collect.ArrayListMultimap;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
@@ -24,21 +27,13 @@
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.mcast.cli.McastGroupCompleter;
import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.mcast.McastRole;
-import org.onosproject.segmentrouting.storekey.McastStoreKey;
-import java.util.Collection;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static com.google.common.base.Strings.isNullOrEmpty;
-import static org.onosproject.segmentrouting.mcast.McastRole.EGRESS;
-import static org.onosproject.segmentrouting.mcast.McastRole.INGRESS;
-import static org.onosproject.segmentrouting.mcast.McastRole.TRANSIT;
/**
* Command to show the list of mcast trees.
@@ -51,9 +46,9 @@
McastGroupCompleter completer;
// Format for group line
- private static final String G_FORMAT_MAPPING = "group=%s, ingress=%s, transit=%s, egress=%s";
+ private static final String G_FORMAT_MAPPING = "group=%s";
// Format for sink line
- private static final String S_FORMAT_MAPPING = "\tsink=%s\tpath=%s";
+ private static final String S_FORMAT_MAPPING = " sink=%s\tpath=%s";
@Option(name = "-gAddr", aliases = "--groupAddress",
description = "IP Address of the multicast group",
@@ -61,53 +56,76 @@
required = false, multiValued = false)
String gAddr = null;
+ @Option(name = "-src", aliases = "--connectPoint",
+ description = "Source port of:XXXXXXXXXX/XX",
+ valueToShowInHelp = "of:0000000000000001/1",
+ required = false, multiValued = false)
+ String source = null;
+
@Override
protected void execute() {
- // Verify mcast group
- IpAddress mcastGroup = null;
- if (!isNullOrEmpty(gAddr)) {
- mcastGroup = IpAddress.valueOf(gAddr);
-
- }
- // Get SR service
+ // Get SR service and the handled mcast groups
SegmentRoutingService srService = get(SegmentRoutingService.class);
- // Get the mapping
- Map<McastStoreKey, McastRole> keyToRole = srService.getMcastRoles(mcastGroup);
- // Reduce to the set of mcast groups
- Set<IpAddress> mcastGroups = keyToRole.keySet().stream()
- .map(McastStoreKey::mcastIp)
- .collect(Collectors.toSet());
- // Print the trees for each group
+ Set<IpAddress> mcastGroups = ImmutableSet.copyOf(srService.getMcastLeaders(null)
+ .keySet());
+
+ if (!isNullOrEmpty(gAddr)) {
+ mcastGroups = mcastGroups.stream()
+ .filter(mcastIp -> mcastIp.equals(IpAddress.valueOf(gAddr)))
+ .collect(Collectors.toSet());
+ }
+
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode root = mapper.createObjectNode();
+
+ // Print the trees for each group or build json objects
mcastGroups.forEach(group -> {
- // Create a new map for the group
- Multimap<McastRole, DeviceId> roleDeviceIdMap = ArrayListMultimap.create();
- keyToRole.entrySet()
- .stream()
- // Filter only the elements related to this group
- .filter(entry -> entry.getKey().mcastIp().equals(group))
- // For each create a new entry in the group related map
- .forEach(entry -> roleDeviceIdMap.put(entry.getValue(), entry.getKey().deviceId()));
- // Print the map
- printMcastRole(group,
- roleDeviceIdMap.get(INGRESS),
- roleDeviceIdMap.get(TRANSIT),
- roleDeviceIdMap.get(EGRESS)
- );
- // Get sinks paths
- Map<ConnectPoint, List<ConnectPoint>> mcastPaths = srService.getMcastPaths(group);
- // Print the paths
- mcastPaths.forEach(this::printMcastSink);
+ // We want to use source cp only for a specific group
+ ConnectPoint sourcecp = null;
+ if (!isNullOrEmpty(source) &&
+ !isNullOrEmpty(gAddr)) {
+ sourcecp = ConnectPoint.deviceConnectPoint(source);
+ }
+ Multimap<ConnectPoint, List<ConnectPoint>> mcastTree = srService.getMcastTrees(group,
+ sourcecp);
+ // Build a json object for each group
+ if (outputJson()) {
+ root.putPOJO(group.toString(), json(mcastTree));
+ } else {
+ // Banner and then the trees
+ printMcastGroup(group);
+ mcastTree.forEach(this::printMcastSink);
+ }
});
+
+ // Print the json object at the end
+ if (outputJson()) {
+ print("%s", root);
+ }
+
}
- private void printMcastRole(IpAddress mcastGroup,
- Collection<DeviceId> ingress,
- Collection<DeviceId> transit,
- Collection<DeviceId> egress) {
- print(G_FORMAT_MAPPING, mcastGroup, ingress, transit, egress);
+ private void printMcastGroup(IpAddress mcastGroup) {
+ print(G_FORMAT_MAPPING, mcastGroup);
}
private void printMcastSink(ConnectPoint sink, List<ConnectPoint> path) {
print(S_FORMAT_MAPPING, sink, path);
}
-}
+
+ private ObjectNode json(Multimap<ConnectPoint, List<ConnectPoint>> mcastTree) {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode jsonSinks = mapper.createObjectNode();
+ mcastTree.asMap().forEach((sink, paths) -> {
+ ArrayNode jsonPaths = mapper.createArrayNode();
+ paths.forEach(path -> {
+ ArrayNode jsonPath = mapper.createArrayNode();
+ path.forEach(connectPoint -> jsonPath.add(connectPoint.toString()));
+ jsonPaths.addPOJO(jsonPath);
+ });
+ jsonSinks.putPOJO(sink.toString(), jsonPaths);
+ });
+ return jsonSinks;
+ }
+
+}
\ No newline at end of file
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastCacheKey.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastCacheKey.java
index 930432d..55d2131 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastCacheKey.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastCacheKey.java
@@ -45,6 +45,7 @@
*
* @deprecated in 1.12 ("Magpie") release.
*/
+ @Deprecated
public McastCacheKey(IpAddress mcastIp, ConnectPoint sink) {
checkNotNull(mcastIp, "mcastIp cannot be null");
checkNotNull(sink, "sink cannot be null");
@@ -85,6 +86,7 @@
*
* @deprecated in 1.12 ("Magpie") release.
*/
+ @Deprecated
public ConnectPoint sink() {
return sink;
}
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
index 9a53e13..6d8495d 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastHandler.java
@@ -20,10 +20,12 @@
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalCause;
import com.google.common.cache.RemovalNotification;
+import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.onlab.packet.IpAddress;
import org.onlab.packet.VlanId;
@@ -1767,6 +1769,16 @@
entry -> entry.getValue().value().id()));
}
+ /**
+ * Returns the associated roles to the mcast groups or to the single
+ * group if mcastIp is present.
+ *
+ * @param mcastIp the group ip
+ * @return the mapping mcastIp-device to mcast role
+ *
+ * @deprecated in 1.12 ("Magpie") release.
+ */
+ @Deprecated
public Map<McastStoreKey, McastRole> getMcastRoles(IpAddress mcastIp) {
// If mcast ip is present
if (mcastIp != null) {
@@ -1781,6 +1793,15 @@
entry -> entry.getValue().value()));
}
+ /**
+ * Returns the associated paths to the mcast group.
+ *
+ * @param mcastIp the group ip
+ * @return the mapping egress point to mcast path
+ *
+ * @deprecated in 1.12 ("Magpie") release.
+ */
+ @Deprecated
public Map<ConnectPoint, List<ConnectPoint>> getMcastPaths(IpAddress mcastIp) {
Map<ConnectPoint, List<ConnectPoint>> mcastPaths = Maps.newHashMap();
// Get the source
@@ -1798,6 +1819,50 @@
return mcastPaths;
}
+ /**
+ * Returns the associated trees to the mcast group.
+ *
+ * @param mcastIp the group ip
+ * @param sourcecp the source connect point
+ * @return the mapping egress point to mcast path
+ */
+ public Multimap<ConnectPoint, List<ConnectPoint>> getMcastTrees(IpAddress mcastIp,
+ ConnectPoint sourcecp) {
+ Multimap<ConnectPoint, List<ConnectPoint>> mcastTrees = HashMultimap.create();
+ // Get the sources
+ Set<ConnectPoint> sources = mcastUtils.getSources(mcastIp);
+
+ // If we are providing the source, let's filter out
+ if (sourcecp != null) {
+ sources = sources.stream()
+ .filter(source -> source.equals(sourcecp))
+ .collect(Collectors.toSet());
+ }
+
+ // Source cannot be null, we don't know the starting point
+ if (!sources.isEmpty()) {
+ sources.forEach(source -> {
+ // Init steps
+ Map<ConnectPoint, List<ConnectPoint>> mcastPaths = Maps.newHashMap();
+ Set<DeviceId> visited = Sets.newHashSet();
+ List<ConnectPoint> currentPath = Lists.newArrayList(source);
+ // Build recursively the mcast paths
+ buildMcastPaths(source.deviceId(), visited, mcastPaths, currentPath, mcastIp);
+ mcastPaths.forEach(mcastTrees::put);
+ });
+ }
+ return mcastTrees;
+ }
+
+ /**
+ * Build recursively the mcast paths.
+ *
+ * @param toVisit the node to visit
+ * @param visited the visited nodes
+ * @param mcastPaths the current mcast paths
+ * @param currentPath the current path
+ * @param mcastIp the group ip
+ */
private void buildMcastPaths(DeviceId toVisit, Set<DeviceId> visited,
Map<ConnectPoint, List<ConnectPoint>> mcastPaths,
List<ConnectPoint> currentPath, IpAddress mcastIp) {
diff --git a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java
index 924794b..fc89fde 100644
--- a/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java
+++ b/apps/segmentrouting/app/src/main/java/org/onosproject/segmentrouting/mcast/McastUtils.java
@@ -55,7 +55,6 @@
import org.slf4j.Logger;
import java.util.Collection;
-import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@@ -234,10 +233,11 @@
*
* @param mcastIp multicast IP
* @return source connect point or null if not found
+ *
+ * @deprecated in 1.12 ("Magpie") release.
*/
- // FIXME To be addressed with multiple sources support
+ @Deprecated
ConnectPoint getSource(IpAddress mcastIp) {
- // FIXME we should support different types of routes
McastRoute mcastRoute = srManager.multicastRouteService.getRoutes().stream()
.filter(mcastRouteInternal -> mcastRouteInternal.group().equals(mcastIp))
.findFirst().orElse(null);
@@ -247,6 +247,21 @@
}
/**
+ * Gets sources connect points of given multicast group.
+ *
+ * @param mcastIp multicast IP
+ * @return sources connect points or empty set if not found
+ */
+ Set<ConnectPoint> getSources(IpAddress mcastIp) {
+ // FIXME we should support different types of routes
+ McastRoute mcastRoute = srManager.multicastRouteService.getRoutes().stream()
+ .filter(mcastRouteInternal -> mcastRouteInternal.group().equals(mcastIp))
+ .findFirst().orElse(null);
+ return mcastRoute == null ? ImmutableSet.of() :
+ srManager.multicastRouteService.sources(mcastRoute);
+ }
+
+ /**
* Gets sinks of given multicast group.
*
* @param mcastIp multicast IP
@@ -258,7 +273,7 @@
.filter(mcastRouteInternal -> mcastRouteInternal.group().equals(mcastIp))
.findFirst().orElse(null);
return mcastRoute == null ?
- Collections.emptyMap() :
+ ImmutableMap.of() :
srManager.multicastRouteService.routeData(mcastRoute).sinks();
}
diff --git a/apps/segmentrouting/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/segmentrouting/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 4a3329a..71e80ef 100644
--- a/apps/segmentrouting/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/segmentrouting/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -79,6 +79,7 @@
<action class="org.onosproject.segmentrouting.cli.McastTreeListCommand"/>
<optional-completers>
<entry key="-gAddr" value-ref="mcastGroupCompleter"/>
+ <entry key="-src" value-ref="connectpointCompleter"/>
</optional-completers>
</command>
<command>
@@ -93,6 +94,7 @@
<bean id="deviceIdCompleter" class="org.onosproject.cli.net.DeviceIdCompleter"/>
<bean id="pseudowireIdCompleter" class="org.onosproject.segmentrouting.cli.PseudowireIdCompleter"/>
<bean id="mcastGroupCompleter" class="org.onosproject.mcast.cli.McastGroupCompleter"/>
+ <bean id="connectpointCompleter" class="org.onosproject.cli.net.ConnectPointCompleter"/>
</blueprint>
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/McastWebResource.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/McastWebResource.java
new file mode 100644
index 0000000..8202eed
--- /dev/null
+++ b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/McastWebResource.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.segmentrouting.web;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.segmentrouting.SegmentRoutingService;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+
+/**
+ * Query multicast trees.
+ */
+@Path("mcast")
+public class McastWebResource extends AbstractWebResource {
+
+ private ObjectNode encodeMcastTrees(String gAddr, String source) {
+ SegmentRoutingService srService = get(SegmentRoutingService.class);
+ Set<IpAddress> mcastGroups = ImmutableSet.copyOf(srService.getMcastLeaders(null)
+ .keySet());
+
+ if (!isNullOrEmpty(gAddr)) {
+ mcastGroups = mcastGroups.stream()
+ .filter(mcastIp -> mcastIp.equals(IpAddress.valueOf(gAddr)))
+ .collect(Collectors.toSet());
+ }
+
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode root = mapper.createObjectNode();
+
+ // Print the trees for each group or build json objects
+ mcastGroups.forEach(group -> {
+ // We want to use source cp only for a specific group
+ ConnectPoint sourcecp = null;
+ if (!isNullOrEmpty(source) &&
+ !isNullOrEmpty(gAddr)) {
+ sourcecp = ConnectPoint.deviceConnectPoint(source);
+ }
+ Multimap<ConnectPoint, List<ConnectPoint>> mcastTree = srService.getMcastTrees(group, sourcecp);
+ // Build a json object for each group
+ root.putPOJO(group.toString(), json(mcastTree));
+
+ });
+ return root;
+ }
+
+ private ObjectNode json(Multimap<ConnectPoint, List<ConnectPoint>> mcastTree) {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode jsonSinks = mapper.createObjectNode();
+ mcastTree.asMap().forEach((sink, paths) -> {
+ ArrayNode jsonPaths = mapper.createArrayNode();
+ paths.forEach(path -> {
+ ArrayNode jsonPath = mapper.createArrayNode();
+ path.forEach(connectPoint -> jsonPath.add(connectPoint.toString()));
+ jsonPaths.addPOJO(jsonPath);
+ });
+ jsonSinks.putPOJO(sink.toString(), jsonPaths);
+ });
+ return jsonSinks;
+ }
+
+ /**
+ * Get all multicast trees.
+ * Returns an object of the multicast trees.
+ *
+ * @return status of OK
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getMcastTrees() {
+ ObjectNode root = encodeMcastTrees(null, null);
+ return ok(root).build();
+ }
+
+ /**
+ * Get the multicast trees of a group.
+ *
+ * @param group group IP address
+ * @return 200 OK with a multicast routes
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{group}")
+ public Response getRoute(@PathParam("group") String group) {
+ ObjectNode root = encodeMcastTrees(group, null);
+ return ok(root).build();
+ }
+
+ /**
+ * Get the multicast tree of a group.
+ *
+ * @param group group IP address
+ * @param sourcecp source connect point
+ * @return 200 OK with a multicast routes
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{group}/{sourcecp}")
+ public Response getRoute(@PathParam("group") String group,
+ @PathParam("sourcecp") String sourcecp) {
+ ObjectNode root = encodeMcastTrees(group, sourcecp);
+ return ok(root).build();
+ }
+
+}
diff --git a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java
index 4aa1a71..75646d1 100644
--- a/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java
+++ b/apps/segmentrouting/web/src/main/java/org/onosproject/segmentrouting/web/SegmentRoutingWebApplication.java
@@ -26,6 +26,6 @@
public class SegmentRoutingWebApplication extends AbstractWebApplication {
@Override
public Set<Class<?>> getClasses() {
- return getClasses(PseudowireWebResource.class);
+ return getClasses(PseudowireWebResource.class, McastWebResource.class);
}
}