[ONOS-8036] BGP-LS has only partial support for IPv6

- Removed hard-coded Ipv4Address and replaced with the generic
IpAddress wherever necessary
- Added support of AFI = 2 (IPv6) in MPReachNlri and MPUnreachNlri
- Added a new config parameter for IPv6 in BGP Config. This allows
AFI = 2 to be sent in BGP Open messages
- Skipped TLV 1170 and 1173, which were causing exceptions

Change-Id: I76e69021b1d2687754bbf700681070051e347942
diff --git a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpCfg.java b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpCfg.java
index ca462ec..80eec64 100644
--- a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpCfg.java
+++ b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpCfg.java
@@ -67,6 +67,23 @@
         NONE
     }
 
+    enum ConnectionType {
+        /**
+         * Signifies that BGP connects to peer over IPv4 only.
+         */
+        IPV4,
+
+        /**
+         * Signifies that BGP connects to peer over IPv6 only.
+         */
+        IPV6,
+
+        /**
+         * Signifies that BGP connects to peer over IPv4 and IPv6 both.
+         */
+        IPV4_IPV6
+    }
+
     /**
      * Returns the status of the configuration based on this state certain operations like connection is handled.
      *
@@ -359,4 +376,18 @@
      */
     boolean getEvpnCapability();
 
+    /**
+     * Gets the BGP connection type.
+     *
+     * @return BGP connection type.
+     */
+    ConnectionType connectionType();
+
+    /**
+     * Sets the BGP connection type.
+     *
+     * @param connectionType BGP connection type
+     */
+    void setConnectionType(ConnectionType connectionType);
+
 }
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java
index 4346b86..aaddc6d 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpOpenMsg.java
@@ -158,6 +158,24 @@
          */
         Builder setEvpnCapabilityTlv(boolean isEvpnCapabilitySet);
 
+        /**
+         * Sets if the BGP connection uses IPv4 Unicast connections.
+         *
+         * @param ipV4UnicastCapabilityTlvSet boolean value to know if IPv4 is used
+         *
+         * @return Builder by setting capabilities
+         */
+        Builder setIpV4UnicastCapabilityTlvSet(boolean ipV4UnicastCapabilityTlvSet);
+
+        /**
+         * Sets if the BGP connection uses IPv6 Unicast connections.
+         *
+         * @param ipV6UnicastCapabilityTlvSet boolean value to know if IPv6 is used
+         *
+         * @return Builder by setting capabilities
+         */
+        Builder setIpV6UnicastCapabilityTlvSet(boolean ipV6UnicastCapabilityTlvSet);
+
         @Override
         Builder setHeader(BgpHeader bgpMsgHeader);
     }
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java
index 8ed830f..cb757e3 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/linkstate/BgpPrefixIPv4LSNlriVer4.java
@@ -56,6 +56,7 @@
     private static final Logger log = LoggerFactory.getLogger(BgpPrefixIPv4LSNlriVer4.class);
 
     public static final int PREFIX_IPV4_NLRITYPE = 3;
+    public static final int PREFIX_IPV6_NLRITYPE = 4;
     public static final int IDENTIFIER_LENGTH = 16;
     private long identifier;
     private byte protocolId;
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java
index 61486ed..716101c 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpOpenMsgVer4.java
@@ -319,6 +319,7 @@
         private boolean isBgpIdSet = false;
         private int bgpId;
         private boolean isIpV4UnicastCapabilityTlvSet = true;
+        private boolean isIpV6UnicastCapabilityTlvSet = false;
         private boolean isLargeAsCapabilityTlvSet = false;
         private boolean isLsCapabilityTlvSet = false;
         private boolean isFlowSpecCapabilityTlvSet = false;
@@ -344,7 +345,14 @@
             if (this.isIpV4UnicastCapabilityTlvSet) {
                 BgpValueType tlv;
                 tlv = new MultiProtocolExtnCapabilityTlv((short) Constants.AFI_IPV4_UNICAST, RES,
-                                                         (byte) Constants.SAFI_IPV4_UNICAST);
+                                                         (byte) Constants.SAFI_UNICAST);
+                this.capabilityTlv.add(tlv);
+            }
+
+            if (this.isIpV6UnicastCapabilityTlvSet) {
+                BgpValueType tlv;
+                tlv = new MultiProtocolExtnCapabilityTlv((short) Constants.AFI_IPV6_UNICAST, RES,
+                                                         (byte) Constants.SAFI_UNICAST);
                 this.capabilityTlv.add(tlv);
             }
 
@@ -460,6 +468,18 @@
             this.isEvpnCapabilityTlvSet = isEvpnCapabilitySet;
             return this;
         }
+
+        @Override
+        public Builder setIpV4UnicastCapabilityTlvSet(boolean isIpV4UnicastCapabilityTlvSet) {
+            this.isIpV4UnicastCapabilityTlvSet = isIpV4UnicastCapabilityTlvSet;
+            return this;
+        }
+
+        @Override
+        public Builder setIpV6UnicastCapabilityTlvSet(boolean isIpV6UnicastCapabilityTlvSet) {
+            this.isIpV6UnicastCapabilityTlvSet = isIpV6UnicastCapabilityTlvSet;
+            return this;
+        }
     }
 
     @Override
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java
index 4c2bd67..0d58651 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LinkStateAttributes.java
@@ -89,6 +89,8 @@
     public static final short ATTR_PREFIX_OSPF_FWD_ADDR = 1156;
     public static final short ATTR_PREFIX_OPAQUE_ATTR = 1157;
 
+    public static final short ATTR_PREFIX_FLAGS = 1170;
+    public static final short ATTR_EXTENDED_ADMINISTRATIVE_GROUP = 1173;
     public static final byte LINKSTATE_ATTRIB_TYPE = 29;
     public static final byte TYPE_AND_LEN = 4;
     private boolean isLinkStateAttribute = false;
@@ -279,9 +281,21 @@
                 bgpLSAttrib = BgpPrefixAttrOpaqueData.read(tempCb);
                 break;
 
+            case ATTR_PREFIX_FLAGS:
+            case ATTR_EXTENDED_ADMINISTRATIVE_GROUP:
+                //We are not using these bytes, but simply skipping them.
+                //If we don't skip but simply ignore these, the while loop
+                //reads wrong bytes and throws BgpParseException
+
+                //TODO : Use these bytes if required
+                int prefixFlagsLength = tempCb.readShort();
+                if (tempCb.readableBytes() > 0) {
+                    tempCb.skipBytes(prefixFlagsLength);
+                }
+                break;
+
             default:
-                throw new BgpParseException(
-                                            "The Bgp-LS Attribute is not supported : "
+                throw new BgpParseException("The Bgp-LS Attribute is not supported : "
                                                     + tlvCodePoint);
             }
 
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java
index 578f4fe..0afb756 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java
@@ -18,7 +18,7 @@
 
 import com.google.common.base.MoreObjects;
 import org.jboss.netty.buffer.ChannelBuffer;
-import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
 import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.onosproject.bgpio.protocol.BgpEvpnNlri;
 import org.onosproject.bgpio.protocol.BgpLSNlri;
@@ -38,6 +38,8 @@
 import java.util.List;
 import java.util.ListIterator;
 
+
+
 /*
  * Provides Implementation of MpReach Nlri BGP Path Attribute.
  */
@@ -52,9 +54,10 @@
     private final int length;
     private final short afi;
     private final byte safi;
-    private final Ip4Address ipNextHop;
+    private final IpAddress ipNextHop;
     private BgpFlowSpecNlri bgpFlowSpecNlri;
     private List<BgpEvpnNlri> evpnNlri;
+    public static final int ONE_BYTE_LENGTH = 8;
 
     /**
      * Constructor to initialize parameters.
@@ -65,7 +68,7 @@
      * @param ipNextHop nexthop IpAddress
      * @param length of MpReachNlri
      */
-    public MpReachNlri(List<BgpLSNlri> mpReachNlri, short afi, byte safi, Ip4Address ipNextHop, int length) {
+    public MpReachNlri(List<BgpLSNlri> mpReachNlri, short afi, byte safi, IpAddress ipNextHop, int length) {
         this.mpReachNlri = mpReachNlri;
         this.isMpReachNlri = true;
         this.ipNextHop = ipNextHop;
@@ -99,7 +102,7 @@
      * @param safi      safi
      * @param ipNextHop IP Nexthop
      */
-    public MpReachNlri(List<BgpEvpnNlri> evpnNlri, short afi, byte safi, Ip4Address ipNextHop) {
+    public MpReachNlri(List<BgpEvpnNlri> evpnNlri, short afi, byte safi, IpAddress ipNextHop) {
         this.mpReachNlri = null;
         this.length = 42;
         this.ipNextHop = ipNextHop;
@@ -226,7 +229,7 @@
         ChannelBuffer tempCb = cb.readBytes(parseFlags.getLength());
         short afi = 0;
         byte safi = 0;
-        Ip4Address ipNextHop = null;
+        IpAddress ipNextHop = null;
         while (tempCb.readableBytes() > 0) {
             afi = tempCb.readShort();
             safi = tempCb.readByte();
@@ -239,7 +242,7 @@
                 if (ipAddress.isMulticastAddress()) {
                     throw new BgpParseException("Multicast not supported");
                 }
-                ipNextHop = Ip4Address.valueOf(ipAddress);
+                ipNextHop = IpAddress.valueOf(ipAddress);
                 byte reserved = tempCb.readByte();
 
                 while (tempCb.readableBytes() > 0) {
@@ -258,6 +261,9 @@
                         bgpLSNlri = BgpLinkLsNlriVer4.read(tempBuf, afi, safi);
                         break;
                     case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV4_NLRITYPE:
+                    case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV6_NLRITYPE:
+                        //RFC 7752 : Structure of IPv4 and IPv6 is same
+
                         bgpLSNlri = BgpPrefixIPv4LSNlriVer4.read(tempBuf, afi, safi);
                         break;
                     default:
@@ -279,7 +285,7 @@
                         if (ipAddress.isMulticastAddress()) {
                             throw new BgpParseException("Multicast not supported");
                         }
-                        ipNextHop = Ip4Address.valueOf(ipAddress);
+                        ipNextHop = IpAddress.valueOf(ipAddress);
                     }
 
                     byte reserved = tempCb.readByte();
@@ -360,12 +366,11 @@
                 List<BgpEvpnNlri> eVpnComponents = null;
 
                 byte nextHopLen = tempCb.readByte();
-                InetAddress ipAddress = Validation.toInetAddress(nextHopLen,
-                                                                 tempCb);
+                InetAddress ipAddress = Validation.toInetAddress(nextHopLen, tempCb);
                 if (ipAddress.isMulticastAddress()) {
                     throw new BgpParseException("Multicast not supported");
                 }
-                ipNextHop = Ip4Address.valueOf(ipAddress);
+                ipNextHop = IpAddress.valueOf(ipAddress);
                 byte reserved = tempCb.readByte();
                 while (tempCb.readableBytes() > 0) {
                     BgpEvpnNlri eVpnComponent = BgpEvpnNlriImpl.read(tempCb);
@@ -377,6 +382,27 @@
                 return new MpReachNlri(eVpnComponents, afi, safi, ipNextHop);
 
 
+            } else if ((afi == Constants.AFI_IPV4_UNICAST && safi == Constants.SAFI_UNICAST)
+                    || (afi == Constants.AFI_IPV6_UNICAST && safi == Constants.SAFI_UNICAST)) {
+                byte nextHopLen = tempCb.readByte();
+                InetAddress ipAddress = Validation.toInetAddress(nextHopLen, tempCb);
+                if (ipAddress.isMulticastAddress()) {
+                    throw new BgpParseException("Multicast not supported");
+                }
+                ipNextHop = IpAddress.valueOf(ipAddress);
+                byte snpa = tempCb.readByte();
+
+                //Right now, we do not know where to use these bytes so we skip them
+                //If we do not skip, there are errors in reading subsequent TLVs
+
+                //TODO : Use this info, if required
+                if (tempCb.readableBytes() > 0) {
+                    int mpReachNlriPrefixLength = tempCb.readByte() / ONE_BYTE_LENGTH; //Convert bits to bytes
+
+                    tempCb.skipBytes(mpReachNlriPrefixLength);
+                }
+
+                return new MpReachNlri(mpReachNlri, afi, safi, ipNextHop, parseFlags.getLength());
             } else {
                 throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
             }
@@ -403,7 +429,7 @@
      *
      * @return Nexthop IpAddress
      */
-    public Ip4Address nexthop4() {
+    public IpAddress nexthop() {
         return this.ipNextHop;
     }
 
@@ -473,9 +499,15 @@
             cb.writeShort(0);
             cb.writeShort(afi);
             cb.writeByte(safi);
-            // ip address length
-            cb.writeByte(0x04);
-            cb.writeInt(ipNextHop.toInt());
+            // ip address length and then octets
+            byte[] ipnextHopOctets = ipNextHop.toOctets();
+            byte ipAddrLen = (byte) (ipnextHopOctets.length);
+            cb.writeByte(ipAddrLen);
+
+            for (int temp = 0; temp < ipAddrLen; temp++) {
+                cb.writeByte(ipnextHopOctets[temp]);
+            }
+
             //sub network points of attachment
             cb.writeByte(0);
 
@@ -527,4 +559,4 @@
         // TODO Auto-generated method stub
         return 0;
     }
-}
\ No newline at end of file
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java
index ac63ba7..1fb844c 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java
@@ -219,6 +219,9 @@
                         bgpLSNlri = BgpLinkLsNlriVer4.read(tempBuf, afi, safi);
                         break;
                     case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV4_NLRITYPE:
+                    case BgpPrefixIPv4LSNlriVer4.PREFIX_IPV6_NLRITYPE:
+                        //RFC 7752 : Structure of IPv4 and IPv6 is same
+
                         bgpLSNlri = BgpPrefixIPv4LSNlriVer4.read(tempBuf, afi,
                                                                  safi);
                         break;
@@ -317,6 +320,18 @@
                 }
 
                 return new MpUnReachNlri(eVpnComponents, afi, safi);
+            } else if ((afi == Constants.AFI_IPV4_UNICAST && safi == Constants.SAFI_UNICAST)
+                    || (afi == Constants.AFI_IPV6_UNICAST && safi == Constants.SAFI_UNICAST)) {
+                //Right now, we do not know where to use these bytes so we skip them
+                //If we do not skip, there are errors in reading subsequent TLVs
+
+                //TODO : Use this info, if required
+                int remainingLen = parseFlags.getLength() - 3; //Short for AFI, byte for SAFI
+
+                if (remainingLen > 0) {
+                    tempCb.skipBytes(remainingLen);
+                }
+
             } else {
                 //TODO: check with the values got from capability
                 throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
@@ -477,4 +492,4 @@
                 .add("length", length)
                 .toString();
     }
-}
\ No newline at end of file
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java
index 1839a31..4b6c6eb 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Constants.java
@@ -35,7 +35,8 @@
     public static final byte VPN_SAFI_VALUE = (byte) 0x80;
     public static final byte SAFI_VALUE = 71;
     public static final short AFI_IPV4_UNICAST = 1;
-    public static final byte SAFI_IPV4_UNICAST = 1;
+    public static final short AFI_IPV6_UNICAST = 2;
+    public static final byte SAFI_UNICAST = 1;
     public static final short AFI_FLOWSPEC_VALUE = 1;
     public static final byte SAFI_FLOWSPEC_VALUE = (byte) 133;
     public static final byte VPN_SAFI_FLOWSPEC_VALUE = (byte) 134;
@@ -92,4 +93,4 @@
 
     public static final byte BGP_FLOW_SPEC_LEN_MASK = 0x30;
     public static final byte BGP_FLOW_SPEC_END_OF_LIST_MASK = (byte) 0x80;
-}
\ No newline at end of file
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java
index 3764842..21ab244 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java
@@ -41,6 +41,9 @@
     public static final byte THIRD_BIT = 0x20;
     public static final byte FOURTH_BIT = (byte) 0x10;
     public static final byte IPV4_SIZE = 4;
+    public static final byte IPV6_SIZE = 16;
+    public static final int INET4_LENGTH = 32;
+
     private boolean firstBit;
     private boolean secondBit;
     private boolean thirdBit;
@@ -227,10 +230,20 @@
      * @return object of IpPrefix
      */
     public static IpPrefix bytesToPrefix(byte[] value, int length) {
-        if (value.length != IPV4_SIZE) {
-            value = Arrays.copyOf(value, IPV4_SIZE);
+        if (length <= INET4_LENGTH) {
+            //Treat like IPv4 address
+            if (value.length != IPV4_SIZE) {
+                value = Arrays.copyOf(value, IPV4_SIZE);
+            }
+            IpPrefix ipPrefix = IpPrefix.valueOf(IpAddress.Version.INET, value, length);
+            return ipPrefix;
+        } else {
+            //Treat this like IPv6 address
+            if (value.length != IPV6_SIZE) {
+                value = Arrays.copyOf(value, IPV6_SIZE);
+            }
+            IpPrefix ipPrefix = IpPrefix.valueOf(IpAddress.Version.INET6, value, length);
+            return ipPrefix;
         }
-        IpPrefix ipPrefix = IpPrefix.valueOf(IpAddress.Version.INET, value, length);
-        return ipPrefix;
     }
 }
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java
index 01b7378..c5e6926 100644
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java
@@ -672,9 +672,13 @@
     private void sendHandshakeOpenMessage() throws IOException, BgpParseException {
         int bgpId;
         BgpCfg.FlowSpec flowSpec = bgpconfig.flowSpecCapability();
+        BgpCfg.ConnectionType connectionType = bgpconfig.connectionType();
         boolean flowSpecStatus = false;
         boolean vpnFlowSpecStatus = false;
 
+        boolean ipv4ConnectionTypeStatus = true;
+        boolean ipv6ConnectionTypeStatus = false;
+
         bgpId = Ip4Address.valueOf(bgpconfig.getRouterId()).toInt();
 
         boolean evpnCapability = bgpconfig.getEvpnCapability();
@@ -688,6 +692,17 @@
             vpnFlowSpecStatus = true;
         }
 
+        if (connectionType == BgpCfg.ConnectionType.IPV6) {
+            ipv4ConnectionTypeStatus = false;
+            ipv6ConnectionTypeStatus = true;
+        } else if (connectionType == BgpCfg.ConnectionType.IPV4_IPV6) {
+            ipv4ConnectionTypeStatus = true;
+            ipv6ConnectionTypeStatus = true;
+        } else {
+            ipv4ConnectionTypeStatus = true;
+            ipv6ConnectionTypeStatus = false;
+        }
+
         BgpMessage msg = factory4.openMessageBuilder().setAsNumber((short) bgpconfig.getAsNumber())
                 .setHoldTime(bgpconfig.getHoldTime()).setBgpId(bgpId)
                 .setLsCapabilityTlv(bgpconfig.getLsCapability())
@@ -695,7 +710,10 @@
                 .setFlowSpecCapabilityTlv(flowSpecStatus)
                 .setVpnFlowSpecCapabilityTlv(vpnFlowSpecStatus)
                 .setEvpnCapabilityTlv(evpnCapability)
-                .setFlowSpecRpdCapabilityTlv(bgpconfig.flowSpecRpdCapability()).build();
+                .setFlowSpecRpdCapabilityTlv(bgpconfig.flowSpecRpdCapability())
+                .setIpV4UnicastCapabilityTlvSet(ipv4ConnectionTypeStatus)
+                .setIpV6UnicastCapabilityTlvSet(ipv6ConnectionTypeStatus)
+                .build();
         log.debug("Sending open message to {}", channel.getRemoteAddress());
         channel.write(Collections.singletonList(msg));
 
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java
index e6caee7..c9a9a09 100644
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java
@@ -62,6 +62,9 @@
     private boolean rpdCapability;
     private boolean evpnCapability;
 
+    //Set default connection type as IPv4
+    private ConnectionType connectionType = ConnectionType.IPV4;
+
     /*
      * Constructor to initialize the values.
      */
@@ -153,6 +156,16 @@
     }
 
     @Override
+    public ConnectionType connectionType() {
+        return this.connectionType;
+    }
+
+    @Override
+    public void setConnectionType(ConnectionType connectionType) {
+        this.connectionType = connectionType;
+    }
+
+    @Override
     public String getRouterId() {
         if (this.routerId != null) {
             return this.routerId.toString();
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java
index f4ce9f0..9f32079 100644
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerConfig.java
@@ -15,7 +15,7 @@
  */
 package org.onosproject.bgp.controller.impl;
 
-import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
 import org.onosproject.bgp.controller.BgpConnectPeer;
 import org.onosproject.bgp.controller.BgpPeerCfg;
 
@@ -26,7 +26,7 @@
     private int asNumber;
     private short holdTime;
     private boolean isIBgp;
-    private Ip4Address peerId = null;
+    private IpAddress peerId = null;
     private State state;
     private boolean selfInitiated;
     private BgpConnectPeer connectPeer;
@@ -80,12 +80,12 @@
 
     @Override
     public void setPeerRouterId(String peerId) {
-        this.peerId = Ip4Address.valueOf(peerId);
+        this.peerId = IpAddress.valueOf(peerId);
     }
 
     @Override
     public void setPeerRouterId(String peerId, int asNumber) {
-        this.peerId = Ip4Address.valueOf(peerId);
+        this.peerId = IpAddress.valueOf(peerId);
         this.asNumber = asNumber;
     }
 
diff --git a/providers/bgp/cfg/src/main/java/org/onosproject/provider/bgp/cfg/impl/BgpAppConfig.java b/providers/bgp/cfg/src/main/java/org/onosproject/provider/bgp/cfg/impl/BgpAppConfig.java
index 9f1710a..f76c401 100644
--- a/providers/bgp/cfg/src/main/java/org/onosproject/provider/bgp/cfg/impl/BgpAppConfig.java
+++ b/providers/bgp/cfg/src/main/java/org/onosproject/provider/bgp/cfg/impl/BgpAppConfig.java
@@ -62,6 +62,11 @@
     public static final String PEER_CONNECT_PASSIVE = "passive";
     public static final String PEER_CONNECT_ACTIVE = "active";
 
+    public static final String CONNECTION_TYPE = "connectionType";
+    public static final String CONNECTION_TYPE_IPV4 = "IPV4";
+    public static final String CONNECTION_TYPE_IPV6 = "IPV6";
+    public static final String CONNECTION_TYPE_IPV4_AND_IPV6 = "IPV4_IPV6";
+
     static final int MAX_SHORT_AS_NUMBER = 65535;
     static final long MAX_LONG_AS_NUMBER = 4294967295L;
 
@@ -80,13 +85,13 @@
 
         fields = hasOnlyFields(ROUTER_ID, LOCAL_AS, MAX_SESSION, LS_CAPABILITY,
                                HOLD_TIME, LARGE_AS_CAPABILITY, FLOW_SPEC_CAPABILITY,
-                               FLOW_SPEC_RPD_CAPABILITY, BGP_PEER, EVPN_CAPABILITY) &&
+                               FLOW_SPEC_RPD_CAPABILITY, BGP_PEER, EVPN_CAPABILITY, CONNECTION_TYPE) &&
                 isIpAddress(ROUTER_ID, MANDATORY) && isNumber(LOCAL_AS, MANDATORY) &&
                 isNumber(MAX_SESSION, OPTIONAL, MIN_SESSION_NUMBER, MAX_SESSION_NUMBER)
                 && isNumber(HOLD_TIME, OPTIONAL, MIN_HOLDTIME, MAX_HOLDTIME) &&
                 isBoolean(LS_CAPABILITY, OPTIONAL) && isBoolean(LARGE_AS_CAPABILITY, OPTIONAL) &&
                 isString(FLOW_SPEC_CAPABILITY, OPTIONAL) && isBoolean(FLOW_SPEC_RPD_CAPABILITY, OPTIONAL)
-                && isBoolean(EVPN_CAPABILITY, OPTIONAL);
+                && isBoolean(EVPN_CAPABILITY, OPTIONAL) && isString(CONNECTION_TYPE, OPTIONAL);
 
         if (!fields) {
             return fields;
@@ -168,6 +173,33 @@
     }
 
     /**
+     * Returns BGP connection type from the configuration.
+     *
+     * @return BGP connection type
+     */
+    public String connectionType() {
+        return get(CONNECTION_TYPE, null);
+    }
+
+    /**
+     * Validates the BGP connection type.
+     *
+     * @return true if valid else false
+     */
+    public boolean validateConnectionType() {
+        if (connectionType() != null) {
+            String connectionType = connectionType();
+            if (!connectionType.equals(CONNECTION_TYPE_IPV4) && !connectionType.equals(CONNECTION_TYPE_IPV6)
+                    && !connectionType.equals(CONNECTION_TYPE_IPV4_AND_IPV6)) {
+                log.error("Connection Type is invalid");
+                return false;
+            }
+        }
+        log.debug("Connection Type is valid");
+        return true;
+    }
+
+    /**
      * Validates the flow specification capability.
      *
      * @return true if valid else false
@@ -234,6 +266,10 @@
         if (!validateHoldTime()) {
             return false;
         }
+
+        if (!validateConnectionType()) {
+            return false;
+        }
         return true;
     }
 
diff --git a/providers/bgp/cfg/src/main/java/org/onosproject/provider/bgp/cfg/impl/BgpCfgProvider.java b/providers/bgp/cfg/src/main/java/org/onosproject/provider/bgp/cfg/impl/BgpCfgProvider.java
index c35f4f0..d9268d8 100644
--- a/providers/bgp/cfg/src/main/java/org/onosproject/provider/bgp/cfg/impl/BgpCfgProvider.java
+++ b/providers/bgp/cfg/src/main/java/org/onosproject/provider/bgp/cfg/impl/BgpCfgProvider.java
@@ -152,6 +152,8 @@
                 bgpConfig.connectPeer(nodes.get(i).hostname());
             }
         }
+
+        bgpConfig.setConnectionType(getBgpConnectionTypeFromConfig(config));
     }
 
     /**
@@ -259,6 +261,30 @@
             }
         }
 
+        bgpConfig.setConnectionType(getBgpConnectionTypeFromConfig(config));
+    }
+
+    /**
+    * Function to get Bgp Connection type from config.
+    * @param config The BgpAppConfig from which connection type is to be fetched
+    * @return Bgp connection type
+    */
+    private BgpCfg.ConnectionType getBgpConnectionTypeFromConfig(BgpAppConfig config) {
+        //config cannot be null here, because of the function call sequence
+
+        //But, let's put a sanity check for connectionType
+        if (null == config.connectionType()) {
+            //IPv4 is the default connection type
+            return BgpCfg.ConnectionType.IPV4;
+        }
+
+        if (config.connectionType().equals(BgpAppConfig.CONNECTION_TYPE_IPV4)) {
+            return BgpCfg.ConnectionType.IPV6;
+        } else if (config.connectionType().equals(BgpAppConfig.CONNECTION_TYPE_IPV4_AND_IPV6)) {
+            return BgpCfg.ConnectionType.IPV4_IPV6;
+        } else {
+            return BgpCfg.ConnectionType.IPV4;
+        }
     }
 
     /**
diff --git a/providers/bgp/cli/src/main/java/org/onosproject/bgp/cli/BgpLocalRibDisplay.java b/providers/bgp/cli/src/main/java/org/onosproject/bgp/cli/BgpLocalRibDisplay.java
index 6620865..4e6911f 100644
--- a/providers/bgp/cli/src/main/java/org/onosproject/bgp/cli/BgpLocalRibDisplay.java
+++ b/providers/bgp/cli/src/main/java/org/onosproject/bgp/cli/BgpLocalRibDisplay.java
@@ -314,7 +314,7 @@
                         "RouterID = %s,IsoNodeID = %s,NextHop = %s", pathAttrNlriDetailsLocalRib.localRibAsNum(),
                 pathAttrNlriDetailsLocalRib.localRibIdentifier(), pathAttrNlriDetailsLocalRib.localRibIpAddress(),
                 protocolType.toString(), origin.origin(), localPref.localPref(), bgpAttrRouterIdV4.attrRouterId(),
-                Arrays.toString(isIsNonPseudonode.getIsoNodeId()), mpReachNlri.nexthop4());
+                Arrays.toString(isIsNonPseudonode.getIsoNodeId()), mpReachNlri.nexthop());
     }
 
     private void displayLink() {
@@ -399,9 +399,9 @@
                 bgpLinkAttrUnRsrvdLinkBandwidth.getLinkAttrUnRsrvdLinkBandwidth().toString(),
                 bgpLinkAttrTeDefaultMetric.attrLinkDefTeMetric(), bgpLinkAttrIgpMetric.attrLinkIgpMetric(),
                 Arrays.toString(isIsNonPseudonode.getIsoNodeId()), autonomousSystemTlv.getAsNum(),
-                iPv4AddressTlv.address(), mpReachNlri.nexthop4().toString(),
+                iPv4AddressTlv.address(), mpReachNlri.nexthop().toString(),
                 pathAttrNlriDetailsLocalRib.localRibIpAddress(), origin.origin(), localPref.localPref(),
                 bgpAttrRouterIdV4.attrRouterId());
 
     }
-}
\ No newline at end of file
+}
diff --git a/providers/bgp/route/src/main/java/org/onosproject/provider/bgp/route/impl/BgpRouteProvider.java b/providers/bgp/route/src/main/java/org/onosproject/provider/bgp/route/impl/BgpRouteProvider.java
index 2059e56..bb1c8d1 100644
--- a/providers/bgp/route/src/main/java/org/onosproject/provider/bgp/route/impl/BgpRouteProvider.java
+++ b/providers/bgp/route/src/main/java/org/onosproject/provider/bgp/route/impl/BgpRouteProvider.java
@@ -242,12 +242,12 @@
             List<BgpEvpnNlri> evpnReachNlri = new LinkedList<>();
             List<BgpEvpnNlri> evpnUnreachNlri = new LinkedList<>();
 
-            Ip4Address ipNextHop = null;
+            IpAddress ipNextHop = null;
             while (iterator.hasNext()) {
                 BgpValueType attr = iterator.next();
                 if (attr instanceof MpReachNlri) {
                     MpReachNlri mpReachNlri = (MpReachNlri) attr;
-                    ipNextHop = mpReachNlri.nexthop4();
+                    ipNextHop = mpReachNlri.nexthop();
                     if (mpReachNlri
                             .getNlriDetailsType() == BgpNlriType.EVPN) {
                         evpnReachNlri.addAll(mpReachNlri.bgpEvpnNlri());