2 * Copyright © 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.bgpmanager;
11 import java.net.InetAddress;
12 import java.net.UnknownHostException;
13 import java.util.List;
14 import org.apache.karaf.shell.commands.Command;
15 import org.apache.karaf.shell.commands.Option;
16 import org.apache.karaf.shell.console.OsgiCommandSupport;
17 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
18 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
19 import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
20 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
21 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.TcpMd5SignaturePasswordType;
22 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.Neighbors;
23 import org.opendaylight.yangtools.yang.common.Uint32;
25 @Command(scope = "odl", name = "configure-bgp", description = "")
26 public class ConfigureBgpCli extends OsgiCommandSupport {
27 private static final long AS_MIN = 0;
28 private static final long AS_MAX = 4294967295L;//2^32-1
30 @Option(name = "-op", aliases = {"--operation", "--op"}, description = "[start-bgp-server, stop-bgp-server, "
31 + "add-neighbor, delete-neighbor, add-route, delete-route,graceful-restart, enable-log ]",
32 required = false, multiValued = false)
35 //exec configure-bgp add-neighbor --ip <neighbor-ip> --as-num <as-num> --address-family <af> --use-source-ip
36 // <sip> --ebgp-multihops <em> --next-hop <nh>
37 //exec configure-bgp --op add-route/delete-route --rd <rd> --prefix <prefix> --nexthop <nexthop>
38 // --mac <mac> --l2vni <l2vni> --l3vni <l3vni>
40 @Option(name = "--as-num", description = "as number of the bgp neighbor", required = false, multiValued = false)
41 String asNumber = null;
43 @Option(name = "--ip", description = "ip of the bgp neighbor", required = false, multiValued = false)
46 @Option(name = "--tcp-md5-password", description = "RFC2385 TCP MD5 Signature Option shared secret",
47 required = false, multiValued = false)
48 String md5passwordOption = null;
50 @Option(name = "--address-family", description = "address family of the bgp neighbor "
51 + "lu|evpn|vpnv4|vpnv6",
52 required = false, multiValued = false)
53 String addressFamily = null;
55 @Option(name = "--use-source-ip", description = "source ip to be used for neighborship connection establishment",
56 required = false, multiValued = false)
57 String sourceIp = null;
59 @Option(name = "--ebgp-multihops", description = "ebgp multihops of the bgp neighbor",
60 required = false, multiValued = false)
61 String ebgpMultihops = null;
63 @Option(name = "--router-id", description = "router id of the bgp instance",
64 required = false, multiValued = false)
65 String routerId = null;
67 @Option(name = "--rd", description = "rd of the route",
68 required = false, multiValued = false)
71 @Option(name = "--prefix", description = "prefix of the route",
72 required = false, multiValued = false)
75 @Option(name = "--nexthop", description = "nexthop of the route",
76 required = false, multiValued = false)
77 String nexthop = null;
79 @Option(name = "--mac", description = "mac of the route",
80 required = false, multiValued = false)
83 @Option(name = "--l2vni", description = "l2vni of the route",
84 required = false, multiValued = false)
85 Uint32 l2vni = Uint32.ZERO;
87 @Option(name = "--l3vni", description = "l3vni",
88 required = false, multiValued = false)
89 Uint32 l3vni = Uint32.ZERO;
91 @Option(name = "--stalepath-time", description = "the time delay after bgp restart stalepaths are cleaned",
92 required = false, multiValued = false)
93 String stalePathTime = null;
95 @Option(name = "--log-file-path", description = "bgp log file path",
96 required = false, multiValued = false)
97 String logFile = null;
99 @Option(name = "--log-level", description = "log level emergencies,alerts,critical,errors,warnings,notifications,"
100 + "informational,debugging",
101 required = false, multiValued = false)
102 String logLevel = null;
105 emergencies, alerts, critical, errors, warnings, notifications, informational, debugging
108 private final BgpManager bgpManager;
109 private final BgpConfigurationManager bgpConfigurationManager;
111 public ConfigureBgpCli(BgpManager bgpManager, BgpConfigurationManager bgpConfigurationManager) {
112 this.bgpManager = bgpManager;
113 this.bgpConfigurationManager = bgpConfigurationManager;
117 protected Object doExecute() throws Exception {
119 session.getConsole().println("Please provide valid operation");
121 session.getConsole().println(
122 "exec configure-bgp -op [start-bgp-server | stop-bgp-server | add-neighbor | delete-neighbor|"
123 + " add-route | delete-route | graceful-restart| enable-log ]");
127 case "start-bgp-server":
130 case "stop-bgp-server":
136 case "delete-neighbor":
145 case "graceful-restart":
152 session.getConsole().println("invalid operation");
154 session.getConsole().println(
155 "exec configure-bgp -op [start-bgp-server | stop-bgp-server | add-neighbor | "
156 + "delete-neighbor| graceful-restart| enable-log ]");
161 public boolean validateStalepathTime() {
163 int time = Integer.parseInt(stalePathTime);
164 if (time < 30 || time > 3600) {
165 session.getConsole().println("invalid stale path time valid range [30-3600]" + stalePathTime);
166 printGracefulRestartHelp();
169 } catch (NumberFormatException e) {
170 session.getConsole().println("invalid stale path time" + stalePathTime);
171 printGracefulRestartHelp();
177 private void configureGR() {
178 boolean validStalepathTime = validateStalepathTime();
179 if (!validStalepathTime) {
182 bgpManager.configureGR(Integer.parseInt(stalePathTime));
185 private void deleteNeighbor() {
186 if (ip == null || !validateIp(ip)) {
187 session.getConsole().println("invalid neighbor ip");
188 printDeleteNeighborHelp();
191 long asNo = getAsNumber(ip);
193 session.getConsole().println("neighbor does not exist");
194 printDeleteNeighborHelp();
197 bgpManager.deleteNeighbor(ip);
200 public long getAsNumber(String nbrIp) {
201 Bgp conf = bgpManager.getConfig();
205 List<Neighbors> nbrs = conf.getNeighborsContainer() == null ? null
206 : conf.getNeighborsContainer().getNeighbors();
210 for (Neighbors nbr : nbrs) {
211 if (nbrIp.equals(nbr.getAddress().getValue())) {
212 return nbr.getRemoteAs().toJava();
218 private void stopBgp() {
219 Bgp conf = bgpManager.getConfig();
223 List<Neighbors> nbrs = conf.getNeighborsContainer() == null ? null
224 : conf.getNeighborsContainer().getNeighbors();
225 if (nbrs != null && nbrs.size() > 0) {
226 session.getConsole().println(
227 "error: all BGP congiguration must be deleted before stopping the router instance");
230 bgpManager.stopBgp();
233 private void usage() {
234 session.getConsole().println("usage:");
237 private void printStartBgpHelp() {
239 session.getConsole().println(
240 "exec configure-bgp -op start-bgp-server --as-num <asnum> --router-id <routerid> [--stalepath-time "
244 private void printAddNeighborHelp() {
246 session.getConsole().println(
247 "exec configure-bgp -op add-neighbor --ip <neighbor-ip> --as-num <as-num> [--address-family <af>] "
248 + "[--tcp-md5-password <password>] "
249 + "[--use-source-ip <sip>] [--ebgp-multihops <em> ]");
252 private void printDeleteNeighborHelp() {
254 session.getConsole().println("exec configure-bgp -op delete-neighbor --ip <neighbor-ip>");
257 void printEnableLogHelp() {
259 session.getConsole().println(
260 "exec configure-bgp -op enable-logging --filename <filename> --log-level "
261 + "[emergencies|alerts|critical|errors|warnings|notifications|informational|debugging]");
264 private void printGracefulRestartHelp() {
266 session.getConsole().println("exec configure-bgp -op graceful-restart --stalepath-time <30-3600>");
269 private void startBgp() {
270 boolean validRouterId = false;
272 if (bgpManager.getConfig() != null && bgpManager.getConfig().getAsId() != null) {
273 session.getConsole().println("bgp is already started please use stop-bgp-server and start again");
276 if (!validateAsNumber(asNumber)) {
280 validRouterId = validateIp(routerId);
281 if (!validRouterId) {
282 session.getConsole().println("invalid router id please supply valid ip address");
287 if (stalePathTime != null) {
288 boolean validStalepathTime = validateStalepathTime();
289 if (!validStalepathTime) {
293 bgpManager.startBgp(Long.parseLong(asNumber), routerId,
294 stalePathTime == null ? 0 : Integer.parseInt(stalePathTime), false);
297 protected void addNeighbor() {
298 if (!validateAsNumber(asNumber)) {
299 printAddNeighborHelp();
303 boolean validIp = validateIp(ip);
305 session.getConsole().println("invalid neighbor ip");
306 printAddNeighborHelp();
310 TcpMd5SignaturePasswordType md5secret = null;
311 if (md5passwordOption != null) {
313 md5secret = new TcpMd5SignaturePasswordType(md5passwordOption);
314 } catch (IllegalArgumentException e) {
315 session.getConsole().println(
316 new StringBuilder("invalid MD5 password: ").append(e.getMessage()).toString());
317 printAddNeighborHelp();
322 if (sourceIp != null) {
323 validIp = validateIp(sourceIp);
325 session.getConsole().println("invalid source ip");
326 printAddNeighborHelp();
331 if (ebgpMultihops != null) {
333 long val = Long.parseLong(ebgpMultihops);
334 if (val < 1 || val > 255) {
335 session.getConsole().println("invalid ebgpMultihops number , valid range [1,255] "
337 printAddNeighborHelp();
340 } catch (NumberFormatException e) {
341 session.getConsole().println("invalid ebgpMultihops number, valid range [1-255]"
343 printAddNeighborHelp();
347 if (addressFamily != null) {
348 if (!addressFamily.equals("lu") && !addressFamily.equals("vpnv4")
349 && !addressFamily.equals("vpnv6")
350 && !addressFamily.equals("evpn")) {
351 session.getConsole().println("error: Address family must be lu/evpn/vpnv4/vpnv6 ");
357 if (addressFamily.equals("vpnv6")) {
360 } else if (addressFamily.equals("evpn")) {
363 } else if (addressFamily.equals("lu")) {
366 } else if (addressFamily.equals("vpnv4")) {
370 session.getConsole().println(
371 "invalid addressFamily valid values lu/evpn/vpnv4/vpnv6");
372 printAddNeighborHelp();
376 if (getAsNumber(ip) != -1) {
377 session.getConsole().println("neighbor with ip " + ip + " already exists");
380 bgpConfigurationManager.addNeighbor(ip, Long.parseLong(asNumber), md5secret);
381 if (addressFamily != null) {
382 bgpConfigurationManager.addAddressFamily(ip, af_afi.AFI_IP.getValue(),
383 af_safi.valueOf(addressFamily).getValue());
385 if (ebgpMultihops != null) {
386 bgpConfigurationManager.addEbgpMultihop(ip, Integer.parseInt(ebgpMultihops));
388 if (sourceIp != null) {
389 bgpConfigurationManager.addUpdateSource(ip, sourceIp);
393 protected void addRoute() {
394 bgpConfigurationManager.onUpdatePushRoute(protocol_type.PROTOCOL_L3VPN, rd, prefix,
395 0, nexthop, mac, l3vni, l2vni, null, null);
398 protected void deleteRoute() {
399 bgpConfigurationManager.onUpdateWithdrawRoute(protocol_type.PROTOCOL_L3VPN, rd, prefix,
403 private boolean validateIp(String inputIp) {
404 boolean validIp = false;
406 if (inputIp != null) {
407 InetAddress addr = InetAddress.getByName(inputIp);
408 if (addr.isMulticastAddress()) {
409 session.getConsole().println("ip cannot be multicast address");
412 if (addr.isLoopbackAddress()) {
413 session.getConsole().println("ip cannot be loopback address");
416 byte[] addrBytes = addr.getAddress();
417 int lastPart = addrBytes[3] & 0xFF;
418 int firstPart = addrBytes[0] & 0xFF;
419 if (firstPart == 0) {
420 return false;//cannot start with 0 "0.1.2.3"
422 if (lastPart == 0 || lastPart == 255) {
427 } catch (UnknownHostException e) {
433 private void enableBgpLogLevel() {
434 if (logFile == null) {
435 session.getConsole().println("Please provide log file name ");
437 session.getConsole().println(
438 "exec configure-bgp -op enable-log --log-file-path <logfile> --log-level <level>");
441 boolean validLoglevel = false;
443 LogLevels.valueOf(logLevel);
444 validLoglevel = true;
445 } catch (IllegalArgumentException e) {
448 if (!validLoglevel) {
449 session.getConsole().println(
450 "Please provide valid log level "
451 + "emergencies|alerts|critical|errors|warnings|notifications|informational|debugging");
453 session.getConsole().println(
454 "exec configure-bgp -op enable-log --log-file-path <logfile> --log-level <level>");
457 bgpManager.setQbgpLog(logFile, logLevel);
460 private boolean validateAsNumber(String strAsnum) {
463 long asNum = Long.parseLong(strAsnum);
464 if (asNum == 0L || asNum == 65535L || asNum == 23456L) {
465 session.getConsole().println("reserved AS Number supplied ");
468 if (asNum <= AS_MIN || asNum > AS_MAX) {
469 session.getConsole().println("invalid AS Number , supported range [1," + AS_MAX + "]");
472 } catch (NumberFormatException e) {
473 session.getConsole().println("invalid AS Number " + asNumber);