2 * Copyright (c) 2015 - 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netvirt.fibmanager.shell;
11 import java.io.PrintStream;
12 import java.net.Inet4Address;
13 import java.net.Inet6Address;
14 import java.net.InetAddress;
15 import java.net.UnknownHostException;
16 import java.util.List;
17 import java.util.Locale;
19 import org.apache.karaf.shell.commands.Argument;
20 import org.apache.karaf.shell.commands.Command;
21 import org.apache.karaf.shell.commands.Option;
22 import org.apache.karaf.shell.console.OsgiCommandSupport;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.opendaylight.genius.datastoreutils.ExpectedDataObjectNotFoundException;
25 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
26 import org.opendaylight.mdsal.binding.api.DataBroker;
27 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
28 import org.opendaylight.mdsal.common.api.ReadFailedException;
29 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase.EncapType;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePathsKey;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
42 @Command(scope = "vpnservice", name = "fib-show", description = "Displays fib entries.\t"
43 + "To get more help use cli fib-show fullHelp")
44 public class ShowFibCommand extends OsgiCommandSupport {
46 private static final Logger LOG = LoggerFactory.getLogger(ShowFibCommand.class);
48 private static final String TABULAR_FORMAT = " %-7s %-20s %-20s %-7s %-7s";
49 private static final String HEADER = String.format(TABULAR_FORMAT, "RD", "Prefix", "NextHop", "Label", "Origin")
50 + "\n -------------------------------------------------------------------";
51 private static final String ADDRFAMILY = "--addr-family";
52 private static final String SUBNET = "--subnet";
54 @Argument(name = "addFam|fullHelp", description = "type of address families to show, or full help cli",
55 required = false, multiValued = false)
56 private final String options = null;
58 @Option(name = ADDRFAMILY, aliases = {"-af"},
59 description = "show address family ipv4 and/or ipv6 and/or l2vpn",
60 required = false, multiValued = true)
61 private final List<String> addrFamList = null;
63 @Option(name = SUBNET, aliases = {"-sub"},
64 description = "show only one IP or subnet sorted by mask ex \"x.x.x.x/32\" or \"2001::1/128\"",
65 required = false, multiValued = true)
66 private final String prefixOrSubnetOption = null;
67 private String prefixOrSubnet = null;
69 private SingleTransactionDataBroker singleTxDb;
71 public void setDataBroker(DataBroker dataBroker) {
72 this.singleTxDb = new SingleTransactionDataBroker(dataBroker);
77 protected Object doExecute() {
78 PrintStream console = session.getConsole();
79 if (prefixOrSubnetOption != null && prefixOrSubnetOption.length() > 0) {
80 prefixOrSubnet = prefixOrSubnetOption.replace("[", "");
81 prefixOrSubnet = prefixOrSubnet.replace("]", "");
82 if (!prefixOrSubnet.contains("/")) {
83 String maskFull = null;
85 Inet4Address tempAdd = (Inet4Address) InetAddress.getByName(prefixOrSubnet);
87 } catch (SecurityException | UnknownHostException | ClassCastException e) {
90 if (maskFull == null) {
92 Inet6Address tempAdd = (Inet6Address) InetAddress.getByName(prefixOrSubnet);
94 } catch (SecurityException | UnknownHostException | ClassCastException e) {
98 if (maskFull == null) {
99 console.println("a part of cli " + SUBNET + " is wrong => " + prefixOrSubnet);
100 return usage(console);
102 prefixOrSubnet += maskFull;
105 console.println(HEADER);
106 if (options == null && prefixOrSubnet == null && (addrFamList == null || addrFamList.isEmpty())) {
107 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
109 FibEntries fibEntries = singleTxDb.syncRead(LogicalDatastoreType.CONFIGURATION, id);
111 Map<VrfTablesKey, VrfTables> keyVrfTablesMap = fibEntries.getVrfTables();
112 if (keyVrfTablesMap == null || keyVrfTablesMap.isEmpty()) {
113 console.println(" No Fib entries found");
117 for (VrfTables vrfTable : keyVrfTablesMap.values()) {
118 printVrfTable(vrfTable, console);
120 } catch (ExpectedDataObjectNotFoundException e404) {
121 /* This is always thrown the first time FIB DS is accessed,
122 and no route have yet been configured in it. So, no need to print FATAL on the console.
124 String errMsg = "FATAL: fib-entries container is missing from MD-SAL";
125 LOG.error(errMsg, e404);
126 } catch (ReadFailedException rfe) {
127 String errMsg = "Internal Error occurred while processing vpnservice:fib-show command";
128 console.println("\n" + errMsg);
129 LOG.error(errMsg, rfe);
133 String optionsLowerCase = options != null ? options.toLowerCase(Locale.getDefault()) : "";
134 switch (optionsLowerCase) {
136 return usage(console);
140 if ((addrFamList == null || addrFamList.isEmpty()) && (prefixOrSubnet == null
141 || prefixOrSubnet.indexOf("/") < 5)) {
142 console.println("any address family is requiered or " + SUBNET + " is wrong");
145 boolean isIpv4 = false;
146 boolean isIpv6 = false;
147 boolean isL2vpn = false;
148 if (addrFamList != null && addrFamList.size() > 0) {
149 for (String addF : addrFamList) {
150 switch (addF.toLowerCase(Locale.getDefault())) {
164 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
166 FibEntries fibEntries = singleTxDb.syncRead(LogicalDatastoreType.CONFIGURATION, id);
168 Map<VrfTablesKey, VrfTables> keyVrfTablesMap = fibEntries.getVrfTables();
169 if (keyVrfTablesMap == null || keyVrfTablesMap.isEmpty()) {
170 console.println(" No Fib entries found");
174 for (VrfTables vrfTable : keyVrfTablesMap.values()) {
175 printVrfTable(vrfTable, console, isIpv4, isIpv6, isL2vpn, prefixOrSubnet);
177 } catch (ExpectedDataObjectNotFoundException e404) {
178 String errMsg = "FATAL: fib-entries container is missing from MD-SAL";
179 console.println("\n" + errMsg);
180 LOG.error(errMsg, e404);
181 } catch (ReadFailedException rfe) {
182 String errMsg = "Internal Error occurred while processing vpnservice:fib-show command";
183 console.println("\n" + errMsg);
184 LOG.error(errMsg, rfe);
192 private void printVrfTable(VrfTables vrfTable, PrintStream console) {
193 printVrfTable(vrfTable, console, true, true, true, null);
196 private void printVrfTable(VrfTables vrfTable, PrintStream console, boolean isIpv4, boolean isIpv6,
197 boolean isL2vpn, @Nullable String inputPrefixOrSubnet) {
199 Map<VrfEntryKey, VrfEntry> keyVrfEntryMap = vrfTable.getVrfEntry();
200 if (keyVrfEntryMap == null) {
201 LOG.warn("Null keyVrfEntryMap found for VPN with rd={}", vrfTable.getRouteDistinguisher());
205 for (VrfEntry vrfEntry : keyVrfEntryMap.values()) {
206 boolean showIt = false;
207 if (isIpv4 && isIpv6 && isL2vpn) {
210 if (!showIt && isIpv4) {
211 LOG.debug("is ipv4 address family=> vrfEntry.getDestPrefix() = {}", vrfEntry.getDestPrefix());
212 showIt = FibHelper.isIpv4Prefix(vrfEntry.getDestPrefix());
214 if (!showIt && isIpv6) {
215 LOG.debug("is ipv6 address family=> vrfEntry.getDestPrefix() = {}", vrfEntry.getDestPrefix());
216 showIt = FibHelper.isIpv6Prefix(vrfEntry.getDestPrefix());
218 if (!showIt && isL2vpn) {
219 if (vrfEntry.getEncapType() != null && !EncapType.Mplsgre.equals(vrfEntry.getEncapType())) {
220 LOG.debug("is l2vpn address family=> vrfEntry.getEncapType() = {}", vrfEntry.getEncapType());
224 if (!showIt && inputPrefixOrSubnet != null) {
225 showIt = FibHelper.isBelongingPrefix(vrfEntry.getDestPrefix(), inputPrefixOrSubnet);
230 Map<RoutePathsKey, RoutePaths> routePathsMap = vrfEntry.getRoutePaths();
231 if (routePathsMap == null || routePathsMap.isEmpty()) {
232 console.println(String.format(TABULAR_FORMAT,
233 vrfTable.getRouteDistinguisher(), vrfEntry.getDestPrefix(),
234 "local", routePathsMap == null ? "<not set>" : "<empty>",
235 vrfEntry.getOrigin()));
238 for (RoutePaths routePath : routePathsMap.values()) {
239 console.println(String.format(TABULAR_FORMAT,
240 vrfTable.getRouteDistinguisher(), vrfEntry.getDestPrefix(),
241 routePath.getNexthopAddress(), routePath.getLabel(),
242 vrfEntry.getOrigin()));
248 private Object usage(PrintStream console) {
249 String nl = System.getProperty("line.separator");
250 console.println("===================================================");
251 console.println("usage cli =>" + nl);
252 console.println("fib-show --help => to get the current help");
253 console.println("fib-show fullHelp => to get the FULL help" + nl);
254 console.println("fib-show -af ipv4 => to get ipv4 address family");
255 console.println("fib-show -af ipv4 -af ipv6 => to get ipv4 and ipv6 address family");
256 console.println("fib-show -af ipv4 -af ipv6 -af l2vpn => to get ipv4 and ipv6 and l2vpn address family");
257 console.println("---------------------------------------------------");
258 console.println("fib-show -sub 40.1.1.0/24 => to get all IPv4 from fib belonging to this subnet");
259 console.println("fib-show -sub 40.1.1.1/32 => to get the IPv4 from fib");
260 console.println("---------------------------------------------------");
261 console.println("fib-show -sub 2001::1/64 => to get all IPv6 from fib belonging to this subnet");
262 console.println("fib-show -sub 2001::1/128 => to get all IPv6 from fib");
263 console.println("===================================================");