blob: 09c795c625c7007581a3d6f7ab704b3f854b889d [file] [log] [blame]
/*
* 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.cli;
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.api.action.Command;
import org.apache.karaf.shell.api.action.Completion;
import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.onlab.packet.IpAddress;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cli.net.ConnectPointCompleter;
import org.onosproject.mcast.cli.McastGroupCompleter;
import org.onosproject.net.ConnectPoint;
import org.onosproject.segmentrouting.SegmentRoutingService;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static com.google.common.base.Strings.isNullOrEmpty;
/**
* Command to show the list of mcast trees.
*/
@Service
@Command(scope = "onos", name = "sr-mcast-tree",
description = "Lists all mcast trees")
public class McastTreeListCommand extends AbstractShellCommand {
// OSGi workaround to introduce package dependency
McastGroupCompleter completer;
// Format for group line
private static final String G_FORMAT_MAPPING = "group=%s";
// Format for sink line
private static final String S_FORMAT_MAPPING = " sink=%s\tpath=%s";
@Option(name = "-gAddr", aliases = "--groupAddress",
description = "IP Address of the multicast group",
valueToShowInHelp = "224.0.0.0",
required = false, multiValued = false)
@Completion(McastGroupCompleter.class)
String gAddr = null;
@Option(name = "-src", aliases = "--connectPoint",
description = "Source port of:XXXXXXXXXX/XX",
valueToShowInHelp = "of:0000000000000001/1",
required = false, multiValued = false)
@Completion(ConnectPointCompleter.class)
String source = null;
@Override
protected void doExecute() {
// Get SR service and the handled mcast groups
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);
if (!mcastTree.isEmpty()) {
// 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 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;
}
}