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;
18 import org.apache.karaf.shell.commands.Argument;
19 import org.apache.karaf.shell.commands.Command;
20 import org.apache.karaf.shell.commands.Option;
21 import org.apache.karaf.shell.console.OsgiCommandSupport;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
26 import org.opendaylight.genius.datastoreutils.ExpectedDataObjectNotFoundException;
27 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
28 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase.EncapType;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 @Command(scope = "vpnservice", name = "fib-show", description = "Displays fib entries.\t"
39 + "To get more help use cli fib-show fullHelp")
40 public class ShowFibCommand extends OsgiCommandSupport {
42 private static final Logger LOG = LoggerFactory.getLogger(ShowFibCommand.class);
44 private static final String TABULAR_FORMAT = " %-7s %-20s %-20s %-7s %-7s";
45 private static final String HEADER = String.format(TABULAR_FORMAT, "RD", "Prefix", "NextHop", "Label", "Origin")
46 + "\n -------------------------------------------------------------------";
47 private static final String ADDRFAMILY = "--addr-family";
48 private static final String SUBNET = "--subnet";
50 @Argument(name = "addFam|fullHelp", description = "type of address families to show, or full help cli",
51 required = false, multiValued = false)
52 private final String options = null;
54 @Option(name = ADDRFAMILY, aliases = {"-af"},
55 description = "show address family ipv4 and/or ipv6 and/or l2vpn",
56 required = false, multiValued = true)
57 private final List<String> addrFamList = null;
59 @Option(name = SUBNET, aliases = {"-sub"},
60 description = "show only one IP or subnet sorted by mask ex \"x.x.x.x/32\" or \"2001::1/128\"",
61 required = false, multiValued = true)
62 private final String prefixOrSubnetOption = null;
63 private String prefixOrSubnet = null;
65 private SingleTransactionDataBroker singleTxDb;
67 public void setDataBroker(DataBroker dataBroker) {
68 this.singleTxDb = new SingleTransactionDataBroker(dataBroker);
73 protected Object doExecute() {
74 PrintStream console = session.getConsole();
75 if (prefixOrSubnetOption != null && prefixOrSubnetOption.length() > 0) {
76 prefixOrSubnet = prefixOrSubnetOption.replace("[", "");
77 prefixOrSubnet = prefixOrSubnet.replace("]", "");
78 if (!prefixOrSubnet.contains("/")) {
79 String maskFull = null;
81 Inet4Address tempAdd = (Inet4Address) InetAddress.getByName(prefixOrSubnet);
83 } catch (SecurityException | UnknownHostException | ClassCastException e) {
86 if (maskFull == null) {
88 Inet6Address tempAdd = (Inet6Address) InetAddress.getByName(prefixOrSubnet);
90 } catch (SecurityException | UnknownHostException | ClassCastException e) {
94 if (maskFull == null) {
95 console.println("a part of cli " + SUBNET + " is wrong => " + prefixOrSubnet);
96 return usage(console);
98 prefixOrSubnet += maskFull;
101 console.println(HEADER);
102 if (options == null && prefixOrSubnet == null && (addrFamList == null || addrFamList.isEmpty())) {
103 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
105 FibEntries fibEntries = singleTxDb.syncRead(LogicalDatastoreType.CONFIGURATION, id);
107 List<VrfTables> vrfTablesList = fibEntries.getVrfTables();
108 if (vrfTablesList == null || vrfTablesList.isEmpty()) {
109 console.println(" No Fib entries found");
113 for (VrfTables vrfTable : vrfTablesList) {
114 printVrfTable(vrfTable, console);
116 } catch (ExpectedDataObjectNotFoundException e404) {
117 /* This is always thrown the first time FIB DS is accessed,
118 and no route have yet been configured in it. So, no need to print FATAL on the console.
120 String errMsg = "FATAL: fib-entries container is missing from MD-SAL";
121 LOG.error(errMsg, e404);
122 } catch (ReadFailedException rfe) {
123 String errMsg = "Internal Error occurred while processing vpnservice:fib-show command";
124 console.println("\n" + errMsg);
125 LOG.error(errMsg, rfe);
129 String optionsLowerCase = options != null ? options.toLowerCase(Locale.getDefault()) : "";
130 switch (optionsLowerCase) {
132 return usage(console);
136 if ((addrFamList == null || addrFamList.isEmpty()) && (prefixOrSubnet == null
137 || prefixOrSubnet.indexOf("/") < 5)) {
138 console.println("any address family is requiered or " + SUBNET + " is wrong");
141 boolean isIpv4 = false;
142 boolean isIpv6 = false;
143 boolean isL2vpn = false;
144 if (addrFamList != null && addrFamList.size() > 0) {
145 for (String addF : addrFamList) {
146 switch (addF.toLowerCase(Locale.getDefault())) {
160 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
162 FibEntries fibEntries = singleTxDb.syncRead(LogicalDatastoreType.CONFIGURATION, id);
164 List<VrfTables> vrfTablesList = fibEntries.getVrfTables();
165 if (vrfTablesList == null || vrfTablesList.isEmpty()) {
166 console.println(" No Fib entries found");
170 for (VrfTables vrfTable : vrfTablesList) {
171 printVrfTable(vrfTable, console, isIpv4, isIpv6, isL2vpn, prefixOrSubnet);
173 } catch (ExpectedDataObjectNotFoundException e404) {
174 String errMsg = "FATAL: fib-entries container is missing from MD-SAL";
175 console.println("\n" + errMsg);
176 LOG.error(errMsg, e404);
177 } catch (ReadFailedException rfe) {
178 String errMsg = "Internal Error occurred while processing vpnservice:fib-show command";
179 console.println("\n" + errMsg);
180 LOG.error(errMsg, rfe);
188 private void printVrfTable(VrfTables vrfTable, PrintStream console) {
189 printVrfTable(vrfTable, console, true, true, true, null);
192 private void printVrfTable(VrfTables vrfTable, PrintStream console, boolean isIpv4, boolean isIpv6,
193 boolean isL2vpn, @Nullable String inputPrefixOrSubnet) {
195 List<VrfEntry> vrfEntries = vrfTable.getVrfEntry();
196 if (vrfEntries == null) {
197 LOG.warn("Null vrfEntries found for VPN with rd={}", vrfTable.getRouteDistinguisher());
201 for (VrfEntry vrfEntry : vrfEntries) {
202 boolean showIt = false;
203 if (isIpv4 && isIpv6 && isL2vpn) {
206 if (!showIt && isIpv4) {
207 LOG.debug("is ipv4 address family=> vrfEntry.getDestPrefix() = {}", vrfEntry.getDestPrefix());
208 showIt = FibHelper.isIpv4Prefix(vrfEntry.getDestPrefix());
210 if (!showIt && isIpv6) {
211 LOG.debug("is ipv6 address family=> vrfEntry.getDestPrefix() = {}", vrfEntry.getDestPrefix());
212 showIt = FibHelper.isIpv6Prefix(vrfEntry.getDestPrefix());
214 if (!showIt && isL2vpn) {
215 if (vrfEntry.getEncapType() != null && !EncapType.Mplsgre.equals(vrfEntry.getEncapType())) {
216 LOG.debug("is l2vpn address family=> vrfEntry.getEncapType() = {}", vrfEntry.getEncapType());
220 if (!showIt && inputPrefixOrSubnet != null) {
221 showIt = FibHelper.isBelongingPrefix(vrfEntry.getDestPrefix(), inputPrefixOrSubnet);
226 List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
227 if (routePaths == null || routePaths.isEmpty()) {
228 console.println(String.format(TABULAR_FORMAT,
229 vrfTable.getRouteDistinguisher(), vrfEntry.getDestPrefix(),
230 "local", routePaths == null ? "<not set>" : "<empty>",
231 vrfEntry.getOrigin()));
234 for (RoutePaths routePath : routePaths) {
235 console.println(String.format(TABULAR_FORMAT,
236 vrfTable.getRouteDistinguisher(), vrfEntry.getDestPrefix(),
237 routePath.getNexthopAddress(), routePath.getLabel(),
238 vrfEntry.getOrigin()));
244 private Object usage(PrintStream console) {
245 String nl = System.getProperty("line.separator");
246 console.println("===================================================");
247 console.println("usage cli =>" + nl);
248 console.println("fib-show --help => to get the current help");
249 console.println("fib-show fullHelp => to get the FULL help" + nl);
250 console.println("fib-show -af ipv4 => to get ipv4 address family");
251 console.println("fib-show -af ipv4 -af ipv6 => to get ipv4 and ipv6 address family");
252 console.println("fib-show -af ipv4 -af ipv6 -af l2vpn => to get ipv4 and ipv6 and l2vpn address family");
253 console.println("---------------------------------------------------");
254 console.println("fib-show -sub 40.1.1.0/24 => to get all IPv4 from fib belonging to this subnet");
255 console.println("fib-show -sub 40.1.1.1/32 => to get the IPv4 from fib");
256 console.println("---------------------------------------------------");
257 console.println("fib-show -sub 2001::1/64 => to get all IPv6 from fib belonging to this subnet");
258 console.println("fib-show -sub 2001::1/128 => to get all IPv6 from fib");
259 console.println("===================================================");