blob: 09c795c625c7007581a3d6f7ab704b3f854b889d [file] [log] [blame]
Pier Luigi0f9635b2018-01-15 18:06:43 +01001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.segmentrouting.cli;
18
Pier71c55772018-04-17 17:25:22 +020019import com.fasterxml.jackson.databind.ObjectMapper;
20import com.fasterxml.jackson.databind.node.ArrayNode;
21import com.fasterxml.jackson.databind.node.ObjectNode;
22import com.google.common.collect.ImmutableSet;
Pier Luigi0f9635b2018-01-15 18:06:43 +010023import com.google.common.collect.Multimap;
Ray Milkeydb38bc82018-09-27 12:32:28 -070024import org.apache.karaf.shell.api.action.Command;
Ray Milkey5105ec32018-10-05 10:17:34 -070025import org.apache.karaf.shell.api.action.Completion;
Ray Milkeydb38bc82018-09-27 12:32:28 -070026import org.apache.karaf.shell.api.action.Option;
Ray Milkey52ca4e92018-09-28 10:58:28 -070027import org.apache.karaf.shell.api.action.lifecycle.Service;
Pier Luigi0f9635b2018-01-15 18:06:43 +010028import org.onlab.packet.IpAddress;
29import org.onosproject.cli.AbstractShellCommand;
Ray Milkey5105ec32018-10-05 10:17:34 -070030import org.onosproject.cli.net.ConnectPointCompleter;
Pier1f87aca2018-03-14 16:47:32 -070031import org.onosproject.mcast.cli.McastGroupCompleter;
Pier Luigi0f9635b2018-01-15 18:06:43 +010032import org.onosproject.net.ConnectPoint;
Pier Luigi0f9635b2018-01-15 18:06:43 +010033import org.onosproject.segmentrouting.SegmentRoutingService;
Pier Luigi0f9635b2018-01-15 18:06:43 +010034
Pier Luigi0f9635b2018-01-15 18:06:43 +010035import java.util.List;
Pier Luigi0f9635b2018-01-15 18:06:43 +010036import java.util.Set;
37import java.util.stream.Collectors;
38
39import static com.google.common.base.Strings.isNullOrEmpty;
Pier Luigi0f9635b2018-01-15 18:06:43 +010040
41/**
42 * Command to show the list of mcast trees.
43 */
Ray Milkey52ca4e92018-09-28 10:58:28 -070044@Service
Pier Luigi0f9635b2018-01-15 18:06:43 +010045@Command(scope = "onos", name = "sr-mcast-tree",
46 description = "Lists all mcast trees")
47public class McastTreeListCommand extends AbstractShellCommand {
48
Pier1f87aca2018-03-14 16:47:32 -070049 // OSGi workaround to introduce package dependency
50 McastGroupCompleter completer;
51
Pier Luigi0f9635b2018-01-15 18:06:43 +010052 // Format for group line
Pier71c55772018-04-17 17:25:22 +020053 private static final String G_FORMAT_MAPPING = "group=%s";
Pier Luigi0f9635b2018-01-15 18:06:43 +010054 // Format for sink line
Pier71c55772018-04-17 17:25:22 +020055 private static final String S_FORMAT_MAPPING = " sink=%s\tpath=%s";
Pier Luigi0f9635b2018-01-15 18:06:43 +010056
Pier1f87aca2018-03-14 16:47:32 -070057 @Option(name = "-gAddr", aliases = "--groupAddress",
58 description = "IP Address of the multicast group",
59 valueToShowInHelp = "224.0.0.0",
Pier Luigi0f9635b2018-01-15 18:06:43 +010060 required = false, multiValued = false)
Ray Milkey5105ec32018-10-05 10:17:34 -070061 @Completion(McastGroupCompleter.class)
Pier1f87aca2018-03-14 16:47:32 -070062 String gAddr = null;
Pier Luigi0f9635b2018-01-15 18:06:43 +010063
Pier71c55772018-04-17 17:25:22 +020064 @Option(name = "-src", aliases = "--connectPoint",
65 description = "Source port of:XXXXXXXXXX/XX",
66 valueToShowInHelp = "of:0000000000000001/1",
67 required = false, multiValued = false)
Ray Milkey5105ec32018-10-05 10:17:34 -070068 @Completion(ConnectPointCompleter.class)
Pier71c55772018-04-17 17:25:22 +020069 String source = null;
70
Pier Luigi0f9635b2018-01-15 18:06:43 +010071 @Override
Ray Milkeydb38bc82018-09-27 12:32:28 -070072 protected void doExecute() {
Pier71c55772018-04-17 17:25:22 +020073 // Get SR service and the handled mcast groups
Pier Luigi0f9635b2018-01-15 18:06:43 +010074 SegmentRoutingService srService = get(SegmentRoutingService.class);
Pier71c55772018-04-17 17:25:22 +020075 Set<IpAddress> mcastGroups = ImmutableSet.copyOf(srService.getMcastLeaders(null)
76 .keySet());
77
78 if (!isNullOrEmpty(gAddr)) {
79 mcastGroups = mcastGroups.stream()
80 .filter(mcastIp -> mcastIp.equals(IpAddress.valueOf(gAddr)))
81 .collect(Collectors.toSet());
82 }
83
84 ObjectMapper mapper = new ObjectMapper();
85 ObjectNode root = mapper.createObjectNode();
86
87 // Print the trees for each group or build json objects
Pier Luigi0f9635b2018-01-15 18:06:43 +010088 mcastGroups.forEach(group -> {
Pier71c55772018-04-17 17:25:22 +020089 // We want to use source cp only for a specific group
90 ConnectPoint sourcecp = null;
91 if (!isNullOrEmpty(source) &&
92 !isNullOrEmpty(gAddr)) {
93 sourcecp = ConnectPoint.deviceConnectPoint(source);
94 }
95 Multimap<ConnectPoint, List<ConnectPoint>> mcastTree = srService.getMcastTrees(group,
96 sourcecp);
Piere99511d2018-04-19 16:47:06 +020097 if (!mcastTree.isEmpty()) {
98 // Build a json object for each group
99 if (outputJson()) {
100 root.putPOJO(group.toString(), json(mcastTree));
101 } else {
102 // Banner and then the trees
103 printMcastGroup(group);
104 mcastTree.forEach(this::printMcastSink);
105 }
Pier71c55772018-04-17 17:25:22 +0200106 }
Pier Luigi0f9635b2018-01-15 18:06:43 +0100107 });
Pier71c55772018-04-17 17:25:22 +0200108
109 // Print the json object at the end
110 if (outputJson()) {
111 print("%s", root);
112 }
113
Pier Luigi0f9635b2018-01-15 18:06:43 +0100114 }
115
Pier71c55772018-04-17 17:25:22 +0200116 private void printMcastGroup(IpAddress mcastGroup) {
117 print(G_FORMAT_MAPPING, mcastGroup);
Pier Luigi0f9635b2018-01-15 18:06:43 +0100118 }
119
120 private void printMcastSink(ConnectPoint sink, List<ConnectPoint> path) {
121 print(S_FORMAT_MAPPING, sink, path);
122 }
Pier71c55772018-04-17 17:25:22 +0200123
124 private ObjectNode json(Multimap<ConnectPoint, List<ConnectPoint>> mcastTree) {
125 ObjectMapper mapper = new ObjectMapper();
126 ObjectNode jsonSinks = mapper.createObjectNode();
127 mcastTree.asMap().forEach((sink, paths) -> {
128 ArrayNode jsonPaths = mapper.createArrayNode();
129 paths.forEach(path -> {
130 ArrayNode jsonPath = mapper.createArrayNode();
131 path.forEach(connectPoint -> jsonPath.add(connectPoint.toString()));
132 jsonPaths.addPOJO(jsonPath);
133 });
134 jsonSinks.putPOJO(sink.toString(), jsonPaths);
135 });
136 return jsonSinks;
137 }
138
139}