Timer and log enhancements in BGP
[netvirt.git] / bgpmanager / impl / src / main / java / org / opendaylight / netvirt / bgpmanager / thrift / client / BgpRouter.java
index b0a0f8b96815128aaaeb46c674f8989727df9907..6aafaa9b6fc99127cf928ad8f17366a2e7b09d99 100644 (file)
@@ -8,19 +8,24 @@
 
 package org.opendaylight.netvirt.bgpmanager.thrift.client;
 
+import static org.opendaylight.netvirt.bgpmanager.oam.BgpConstants.HISTORY_LIMIT;
+import static org.opendaylight.netvirt.bgpmanager.oam.BgpConstants.HISTORY_THRESHOLD;
+
 import com.google.common.annotations.VisibleForTesting;
 import java.net.ConnectException;
+import java.util.Arrays;
 import java.util.List;
 import java.util.function.BooleanSupplier;
 import java.util.function.Supplier;
-import javax.annotation.Nullable;
 import org.apache.thrift.TException;
 import org.apache.thrift.protocol.TBinaryProtocol;
 import org.apache.thrift.transport.TSocket;
 import org.apache.thrift.transport.TTransport;
 import org.apache.thrift.transport.TTransportException;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager;
 import org.opendaylight.netvirt.bgpmanager.RetryOnException;
+import org.opendaylight.netvirt.bgpmanager.thrift.gen.BfdConfigData;
 import org.opendaylight.netvirt.bgpmanager.thrift.gen.BgpConfigurator;
 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Routes;
 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
@@ -28,6 +33,8 @@ import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
 import org.opendaylight.netvirt.bgpmanager.thrift.gen.encap_type;
 import org.opendaylight.netvirt.bgpmanager.thrift.gen.layer_type;
 import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
+import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionHistory;
+import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.LayerType;
 import org.slf4j.Logger;
@@ -42,7 +49,7 @@ public final class BgpRouter {
     private static final int CONNECTION_TIMEOUT = 60000;
 
     private enum Optype {
-        START, STOP, NBR, VRF, PFX, SRC, MHOP, LOG, AF, GR, MP, VRFMP, EOR, DELAY_EOR
+        START, STOP, NBR, VRF, PFX, SRC, MHOP, LOG, AF, GR, MP, VRFMP, EOR, DELAY_EOR, BFD, PEER_STATUS
     }
 
     private static class BgpOp {
@@ -50,6 +57,7 @@ public final class BgpRouter {
 
         Optype type;
         boolean add;
+        boolean multiHop;
         String[] strs;
         int[] ints;
         List<String> irts;
@@ -62,6 +70,8 @@ public final class BgpRouter {
         String macAddress;
         int l2label;
         int l3label;
+        int holdTime;
+        int kaTime;
         encap_type thriftEncapType;
         String routermac;
         public af_afi afi;
@@ -70,10 +80,67 @@ public final class BgpRouter {
 
         BgpOp() {
             strs = new String[3];
-            ints = new int[2];
+            ints = new int[3];
+        }
+
+        BgpOp(BgpOp bgpOp) {
+            strs = new String[3];
+            ints = new int[3];
+            this.strs = bgpOp.strs;
+            this.ints = bgpOp.ints;
+            this.afi = bgpOp.afi;
+            this.safi = bgpOp.safi;
+            this.type = bgpOp.type;
+            this.add = bgpOp.add;
+            this.multiHop = bgpOp.multiHop;
+            this.asNumber = bgpOp.asNumber;
+            this.holdTime = bgpOp.holdTime;
+            this.kaTime = bgpOp.kaTime;
+            this.thriftProtocolType = bgpOp.thriftProtocolType;
+            this.thriftLayerType = bgpOp.thriftLayerType;
+            this.ethernetTag = bgpOp.ethernetTag;
+            this.esi = bgpOp.esi;
+            this.macAddress = bgpOp.macAddress;
+            this.l2label = bgpOp.l2label;
+            this.l3label = bgpOp.l3label;
+            this.routermac = bgpOp.routermac;
+            this.thriftEncapType = bgpOp.thriftEncapType;
+            this.delayEOR = bgpOp.delayEOR;
+
+        }
+
+        @Override
+        public String toString() {
+            //TODO pretty print
+            return "BgpOp{"
+                    + "type=" + type
+                    + ", add=" + add
+                    + ",multihop=" + multiHop
+                    + ", strs=" + Arrays.toString(strs)
+                    + ", ints=" + Arrays.toString(ints)
+                    + ", irts=" + irts
+                    + ", erts=" + erts
+                    + ", asNumber=" + asNumber
+                    + ", Hold Time=" + holdTime
+                    + ", KA Time=" + kaTime
+                    + ", thriftLayerType=" + thriftLayerType
+                    + ", thriftProtocolType=" + thriftProtocolType
+                    + ", ethernetTag=" + ethernetTag
+                    + ", esi='" + esi + '\''
+                    + ", macAddress='" + macAddress + '\''
+                    + ", l2label=" + l2label
+                    + ", l3label=" + l3label
+                    + ", thriftEncapType=" + thriftEncapType
+                    + ", routermac='" + routermac + '\''
+                    + ", afi=" + afi
+                    + ", delayEOR=" + delayEOR
+                    + ", safi=" + safi
+                    + '}' + '\n';
         }
     }
 
+
+
     private final BgpOp bop = new BgpOp();
     private final Supplier<Bgp> bgpConfigSupplier;
     private final BooleanSupplier isBGPEntityOwner;
@@ -84,16 +151,19 @@ public final class BgpRouter {
     private volatile long startTS;
     private volatile long connectTS;
     private volatile long lastConnectedTS;
+    private final TransactionHistory transactionHistory;
     private volatile boolean configServerUpdated = false;
 
-    private BgpRouter(Supplier<Bgp> bgpConfigSupplier, BooleanSupplier isBGPEntityOwner) {
+    private BgpRouter(Supplier<Bgp> bgpConfigSupplier, BooleanSupplier isBGPEntityOwner,
+                      TransactionHistory transactionHistory) {
         this.bgpConfigSupplier = bgpConfigSupplier;
         this.isBGPEntityOwner = isBGPEntityOwner;
+        this.transactionHistory = transactionHistory;
     }
 
     // private ctor FOR UNIT TESTS ONLY
     private BgpRouter(BgpConfigurator.Client bgpClient) {
-        this(() -> null, () -> false);
+        this(() -> null, () -> false, new TransactionHistory(HISTORY_LIMIT, HISTORY_THRESHOLD));
         this.bgpClient = bgpClient;
     }
 
@@ -103,8 +173,9 @@ public final class BgpRouter {
         return new BgpRouter(bgpClient);
     }
 
-    public static BgpRouter newInstance(Supplier<Bgp> bgpConfigSupplier, BooleanSupplier isEntityBGPOwner) {
-        return new BgpRouter(bgpConfigSupplier, isEntityBGPOwner);
+    public static BgpRouter newInstance(Supplier<Bgp> bgpConfigSupplier, BooleanSupplier isEntityBGPOwner,
+                                        TransactionHistory transactionHistory) {
+        return new BgpRouter(bgpConfigSupplier, isEntityBGPOwner,transactionHistory);
     }
 
     public TTransport getTransport() {
@@ -202,7 +273,7 @@ public final class BgpRouter {
         }
 
         bgpClient = new BgpConfigurator.Client(new TBinaryProtocol(transport));
-        LOG.info("Connected to " + msgPiece);
+        LOG.info("Connected to {}", msgPiece);
         return true;
     }
 
@@ -210,9 +281,15 @@ public final class BgpRouter {
         return isConnected;
     }
 
+    private TransactionType getTransactionType(BgpOp op) {
+        return op.add ? TransactionType.ADD : TransactionType.DELETE;
+    }
+
     private void dispatch(BgpOp op) throws TException, BgpRouterException {
         try {
             dispatchInternal(op);
+            transactionHistory.addToHistory(getTransactionType(op), new BgpOp(op));
+            LOG.trace("History size is {}", transactionHistory.getElements().size());
         } catch (TTransportException tte) {
             LOG.error("dispatch command to qthriftd failed, command: {}, exception:", op.toString(), tte);
             reConnect(tte);
@@ -259,7 +336,7 @@ public final class BgpRouter {
                 setStartTS(System.currentTimeMillis());
                 LOG.debug("startBgp thrift call for AsId {}", op.asNumber);
                 result = bgpClient.startBgp(op.asNumber, op.strs[0],
-                        BgpOp.IGNORE, BgpOp.IGNORE, BgpOp.IGNORE, op.ints[0], op.add);
+                        BgpOp.IGNORE, op.holdTime, op.kaTime, op.ints[0], op.add);
                 LOG.debug("Result of startBgp thrift call for AsId {} : {}", op.asNumber, result);
                 break;
             case STOP:
@@ -349,6 +426,22 @@ public final class BgpRouter {
             case DELAY_EOR:
                 bgpClient.send_enableEORDelay(op.delayEOR);
                 break;
+            case BFD:
+                BfdConfigData bfdConfigData = new BfdConfigData();
+                bfdConfigData.setBfdConfigDataVersion((byte)1);
+                bfdConfigData.setBfdDebounceDown(0);
+                bfdConfigData.setBfdDebounceUp(0);
+                bfdConfigData.setBfdFailureThreshold((byte)op.ints[0]);
+                bfdConfigData.setBfdRxInterval(op.ints[1]);
+                bfdConfigData.setBfdTxInterval(op.ints[2]);
+                bfdConfigData.setBfdMultihop(op.multiHop);
+                result = bop.add
+                        ? bgpClient.enableBFDFailover(bfdConfigData)
+                        : bgpClient.disableBFDFailover();
+                break;
+            case PEER_STATUS:
+                result = bgpClient.getPeerStatus(op.strs[0], op.asNumber).getValue();
+                break;
             default:
                 break;
         }
@@ -357,11 +450,14 @@ public final class BgpRouter {
         }
     }
 
-    public synchronized void startBgp(long asNum, String rtrId, int stalepathTime, boolean announceFbit)
+    public synchronized void startBgp(long asNum, String rtrId, int bgpKaTime, int bgpHoldTime,
+                                      int stalepathTime, boolean announceFbit)
             throws TException, BgpRouterException {
         bop.type = Optype.START;
         bop.add = announceFbit;
         bop.asNumber = asNum;
+        bop.kaTime = bgpKaTime;
+        bop.holdTime = bgpHoldTime;
         bop.ints[0] = stalepathTime;
         bop.strs[0] = rtrId;
         LOG.debug("Starting BGP with as number {} and router ID {} StalePathTime: {}", asNum, rtrId, stalepathTime);
@@ -417,7 +513,7 @@ public final class BgpRouter {
         bop.strs[0] = rd;
         bop.afi = af_afi.findByValue((int)afi);
         bop.safi = af_safi.findByValue((int)safi);
-        LOG.debug("Deleting BGP VRF rd: {} " + rd);
+        LOG.debug("Deleting BGP VRF rd: {}", rd);
         dispatch(bop);
     }
 
@@ -470,6 +566,25 @@ public final class BgpRouter {
         dispatch(bop);
     }
 
+    public synchronized void addBfd(int detectMult, int minRx, int minTx, boolean multiHop)
+            throws TException, BgpRouterException {
+        bop.type = Optype.BFD;
+        bop.add = true;
+        bop.ints[0] = detectMult;
+        bop.ints[1] = minRx;
+        bop.ints[2] = minTx;
+        bop.multiHop = multiHop;
+        LOG.debug("Adding BFD config {} {} {} {}", detectMult, minRx, minTx, multiHop);
+        dispatch(bop);
+    }
+
+    public synchronized void delBfd() throws TException, BgpRouterException {
+        bop.type = Optype.BFD;
+        bop.add = false;
+        LOG.debug("Deleting BFD Config ");
+        dispatch(bop);
+    }
+
     public int initRibSync(BgpSyncHandle handle) throws BgpRouterException {
         if (bgpClient == null) {
             throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
@@ -478,6 +593,7 @@ public final class BgpRouter {
             return BgpRouterException.BGP_ERR_IN_ITER;
         }
         handle.setState(BgpSyncHandle.INITED);
+        handle.setMore(1);
         return 0;
     }
 
@@ -518,6 +634,7 @@ public final class BgpRouter {
 
         // TODO: receive correct protocol_type here, currently populating with dummy protocol type
         Routes outRoutes = bgpClient.getRoutes(protocol_type.PROTOCOL_ANY, op, winSize, afi);
+        handle.setMore(outRoutes.more);
         if (outRoutes.more == 0) {
             handle.setState(BgpSyncHandle.DONE);
         }
@@ -528,7 +645,7 @@ public final class BgpRouter {
         bop.type = Optype.LOG;
         bop.strs[0] = fileName;
         bop.strs[1] = debugLevel;
-        LOG.debug("Setting Log file to BGP VRF rd: {} ", fileName, debugLevel);
+        LOG.debug("Setting Log file to BGP VRF rd: {}, {}", fileName, debugLevel);
         dispatch(bop);
     }
 
@@ -611,7 +728,7 @@ public final class BgpRouter {
     public synchronized void enableMultipath(af_afi afi, af_safi safi) throws TException, BgpRouterException {
         bop.type = Optype.MP;
         bop.add = true;
-        LOG.debug("Enabling multipath for afi: " + afi.getValue() + " safi: " + safi.getValue());
+        LOG.debug("Enabling multipath for afi {}, safi {}", afi.getValue(), safi.getValue());
         bop.ints[0] = afi.getValue();
         bop.ints[1] = safi.getValue();
         dispatch(bop);
@@ -620,7 +737,7 @@ public final class BgpRouter {
     public synchronized void disableMultipath(af_afi afi, af_safi safi) throws TException, BgpRouterException {
         bop.type = Optype.MP;
         bop.add = false;
-        LOG.debug("Disabling multipath for afi: " + afi.getValue() + " safi: " + safi.getValue());
+        LOG.debug("Disabling multipath for afi {}, safi {}", afi.getValue(), safi.getValue());
         bop.ints[0] = afi.getValue();
         bop.ints[1] = safi.getValue();
         dispatch(bop);
@@ -645,5 +762,14 @@ public final class BgpRouter {
         LOG.debug("EOR delay time in Seconds sent");
         dispatch(bop);
     }
+
+    public synchronized void getPeerStatus(String nbrIp, long nbrAsNum)
+            throws TException, BgpRouterException {
+        bop.type = Optype.PEER_STATUS;
+        bop.strs[0] = nbrIp;
+        bop.asNumber = nbrAsNum;
+        dispatch(bop);
+    } // public getPeerStatus( nbrIp, nbrAsNum )
+
 }