Adding BGP provider code to support EVPN

Change-Id: Ic5508749b64a47a70f1aabd9324e9f89e85fa39f
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 992862c..ca462ec 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
@@ -345,4 +345,18 @@
      * @param rpdCapability flow specification RPD capability
      */
     void setFlowSpecRpdCapability(boolean rpdCapability);
+
+    /**
+     * Sets the evpn capability.
+     *
+     * @param evpnCapability evpn capability
+     */
+    void setEvpnCapability(boolean evpnCapability);
+    /**
+     * Gets the evpn capability.
+     *
+     * @return evpn capability
+     */
+    boolean getEvpnCapability();
+
 }
diff --git a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java
index bb2b505..b5cfe5a 100644
--- a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java
+++ b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpController.java
@@ -179,5 +179,25 @@
      * @return closedSessionMap
      */
     Map<String, List<String>> closedSessionMap();
+    /**
+     * Register a listener for BGP message events.
+     *
+     * @param listener the listener to notify
+     */
+    void addRouteListener(BgpRouteListener listener);
+
+    /**
+     * Unregister a listener.
+     *
+     * @param listener the listener to unregister
+     */
+    void removeRouteListener(BgpRouteListener listener);
+
+    /**
+     * Return BGP route listener.
+     *
+     * @return route listener
+     */
+    Set<BgpRouteListener> routeListener();
 
 }
diff --git a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java
index 0dbddeb..ab26173 100644
--- a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java
+++ b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeer.java
@@ -16,7 +16,9 @@
 package org.onosproject.bgp.controller;
 import java.util.List;
 import org.jboss.netty.channel.Channel;
+import org.onlab.packet.IpAddress;
 import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.protocol.BgpEvpnNlri;
 import org.onosproject.bgpio.protocol.BgpFactory;
 import org.onosproject.bgpio.protocol.BgpMessage;
 import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
@@ -140,5 +142,17 @@
      * @param wideCommunity for route policy
      */
     void updateFlowSpec(FlowSpecOperation operType, BgpFlowSpecRouteKey routeKey,
-                               BgpFlowSpecNlri flowSpec, WideCommunity wideCommunity);
+                        BgpFlowSpecNlri flowSpec, WideCommunity wideCommunity);
+
+    /**
+     * Updates evpn rule.
+     *
+     * @param operType     operation type add or delete or update
+     * @param nextHop      next Hop
+     * @param extcommunity extended community
+     * @param evpnNlris    list of evpnNlri
+     */
+    void updateEvpnNlri(FlowSpecOperation operType, IpAddress nextHop,
+                        List<BgpValueType> extcommunity,
+                        List<BgpEvpnNlri> evpnNlris);
 }
diff --git a/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpRouteListener.java b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpRouteListener.java
new file mode 100755
index 0000000..f2df135
--- /dev/null
+++ b/protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpRouteListener.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.bgp.controller;
+
+import org.onosproject.bgpio.protocol.BgpUpdateMsg;
+
+public interface BgpRouteListener {
+
+    /**
+     * Notify that got an update message and operate route.
+     *
+     * @param bgpId bgp identifier
+     * @param msg BGP update message
+     */
+    void processRoute(BgpId bgpId, BgpUpdateMsg msg);
+
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpEvpnNlri.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpEvpnNlri.java
new file mode 100755
index 0000000..212b921
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpEvpnNlri.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.bgpio.protocol;
+
+import org.onosproject.bgpio.protocol.evpn.BgpEvpnNlriData;
+import org.onosproject.bgpio.protocol.evpn.BgpEvpnRouteType;
+import org.onosproject.bgpio.types.BgpValueType;
+
+/**
+ * Abstraction of an entity providing BGP-EVPN NLRI.
+ */
+public interface BgpEvpnNlri extends BgpValueType {
+
+    /**
+     * Returns route type in Nlri.
+     *
+     * @return route type in Nlri
+     */
+    BgpEvpnRouteType getRouteType();
+
+    /**
+     * Returns route type specific Nlri.
+     *
+     * @return route type in Nlri
+     */
+    BgpEvpnNlriData getNlri();
+
+}
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 708bc06..4346b86 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
@@ -148,6 +148,16 @@
          */
         Builder setFlowSpecRpdCapabilityTlv(boolean isFlowSpecRpdCapabilitySet);
 
+        /**
+         * Sets Evpn capability and return its builder.
+         *
+         * @param isEvpnCapabilitySet boolean value to know whether evpn
+         *            capability is set or not
+         *
+         * @return builder by setting capabilities
+         */
+        Builder setEvpnCapabilityTlv(boolean isEvpnCapabilitySet);
+
         @Override
         Builder setHeader(BgpHeader bgpMsgHeader);
     }
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnNlriData.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnNlriData.java
new file mode 100755
index 0000000..e91e94a
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnNlriData.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.bgpio.protocol.evpn;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface BgpEvpnNlriData {
+
+    /**
+     * Returns the Type of RouteTypeSpefic.
+     *
+     * @return short value of type
+     */
+    BgpEvpnRouteType getType();
+
+    /**
+     * Writes the byte Stream of BGP Message to channel buffer.
+     *
+     * @param cb channel buffer
+     * @return length written to channel buffer
+     */
+    int write(ChannelBuffer cb);
+
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnNlriImpl.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnNlriImpl.java
new file mode 100755
index 0000000..cfe0530
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnNlriImpl.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.bgpio.protocol.evpn;
+
+import com.google.common.base.MoreObjects;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.protocol.BgpEvpnNlri;
+import org.onosproject.bgpio.types.BgpErrorType;
+import org.onosproject.bgpio.util.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of Evpn NLRI.
+ */
+public class BgpEvpnNlriImpl implements BgpEvpnNlri {
+
+    /*
+     * REFERENCE : RFC 7432 BGP MPLS-Based Ethernet VPN
+                 +-----------------------------------+
+                 |    Route Type (1 octet)           |
+                 +-----------------------------------+
+                 |     Length (1 octet)              |
+                 +-----------------------------------+
+                 | Route Type specific (variable)    |
+                 +-----------------------------------+
+
+                Figure : The format of the EVPN NLRI
+     */
+
+    protected static final Logger log = LoggerFactory
+            .getLogger(BgpEvpnNlriImpl.class);
+
+    // total length of route type and length
+    public static final short TYPE_AND_LEN = 2;
+    private byte routeType;
+    private BgpEvpnNlriData routeTypeSpec;
+
+    /**
+     * Resets parameters.
+     */
+    public BgpEvpnNlriImpl() {
+        this.routeType = Constants.BGP_EVPN_MAC_IP_ADVERTISEMENT;
+        this.routeTypeSpec = null;
+
+    }
+
+    /**
+     * Constructor to initialize parameters for BGP EvpnNlri.
+     *
+     * @param routeType       route Type
+     * @param routeTypeSpefic route type specific
+     */
+    public BgpEvpnNlriImpl(byte routeType, BgpEvpnNlriData routeTypeSpefic) {
+        this.routeType = routeType;
+        this.routeTypeSpec = routeTypeSpefic;
+    }
+
+    /**
+     * Reads from channelBuffer and parses Evpn Nlri.
+     *
+     * @param cb ChannelBuffer
+     * @return object of BgpEvpnNlriVer4
+     * @throws BgpParseException while parsing Bgp Evpn Nlri
+     */
+    public static BgpEvpnNlriImpl read(ChannelBuffer cb)
+            throws BgpParseException {
+
+        BgpEvpnNlriData routeNlri = null;
+
+        if (cb.readableBytes() > 0) {
+            ChannelBuffer tempBuf = cb.copy();
+            byte type = cb.readByte();
+            byte length = cb.readByte();
+            if (cb.readableBytes() < length) {
+                throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR,
+                                            BgpErrorType.OPTIONAL_ATTRIBUTE_ERROR,
+                                            tempBuf.readBytes(cb.readableBytes()
+                                                                      + TYPE_AND_LEN));
+            }
+            ChannelBuffer tempCb = cb.readBytes(length);
+            switch (type) {
+                case BgpEvpnRouteType2Nlri.TYPE:
+                    routeNlri = BgpEvpnRouteType2Nlri.read(tempCb);
+                    break;
+                default:
+                    log.info("Discarding, EVPN route type {}", type);
+                    throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR,
+                                                BgpErrorType.MISSING_WELLKNOWN_ATTRIBUTE, null);
+                    //        break;
+            }
+            return new BgpEvpnNlriImpl(type, routeNlri);
+        } else {
+            return new BgpEvpnNlriImpl();
+        }
+
+    }
+
+    @Override
+    public BgpEvpnNlriData getNlri() {
+        return routeTypeSpec;
+    }
+
+    @Override
+    public BgpEvpnRouteType getRouteType() {
+        switch (routeType) {
+            case Constants.BGP_EVPN_ETHERNET_AUTO_DISCOVERY:
+                return BgpEvpnRouteType.ETHERNET_AUTO_DISCOVERY;
+            case Constants.BGP_EVPN_MAC_IP_ADVERTISEMENT:
+                return BgpEvpnRouteType.MAC_IP_ADVERTISEMENT;
+            case Constants.BGP_EVPN_INCLUSIVE_MULTICASE_ETHERNET:
+                return BgpEvpnRouteType.INCLUSIVE_MULTICASE_ETHERNET;
+            case Constants.BGP_EVPN_ETHERNET_SEGMENT:
+                return BgpEvpnRouteType.ETHERNET_SEGMENT;
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass()).omitNullValues()
+                .add("routeType", routeType)
+                .add("routeTypeSpefic ", routeTypeSpec).toString();
+    }
+
+    @Override
+    public short getType() {
+        return routeType;
+    }
+
+
+    @Override
+    public int write(ChannelBuffer cb) {
+        int iLenStartIndex = cb.writerIndex();
+        cb.writeByte(routeType);
+        int iSpecStartIndex = cb.writerIndex();
+        cb.writeByte(0);
+        switch (routeType) {
+            case BgpEvpnRouteType2Nlri.TYPE:
+                ((BgpEvpnRouteType2Nlri) routeTypeSpec).write(cb);
+                break;
+            default:
+                break;
+        }
+        cb.setByte(iSpecStartIndex,
+                   (short) (cb.writerIndex() - iSpecStartIndex + 1));
+        return cb.writerIndex() - iLenStartIndex;
+    }
+
+    @Override
+    public int compareTo(Object o) {
+        return 0;
+    }
+
+
+}
+
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnRouteType.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnRouteType.java
new file mode 100755
index 0000000..6b919c3
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnRouteType.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.bgpio.protocol.evpn;
+
+/**
+ * Enum to provide EVPN RouteType.
+ */
+public enum BgpEvpnRouteType {
+    ETHERNET_AUTO_DISCOVERY(1), MAC_IP_ADVERTISEMENT(2),
+    INCLUSIVE_MULTICASE_ETHERNET(3), ETHERNET_SEGMENT(4);
+    int value;
+
+    /**
+     * Assign val with the value as the route type.
+     *
+     * @param val route type
+     */
+    BgpEvpnRouteType(int val) {
+        value = val;
+    }
+
+    /**
+     * Returns value of route type.
+     *
+     * @return route type
+     */
+    public byte getType() {
+        return (byte) value;
+    }
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnRouteType2Nlri.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnRouteType2Nlri.java
new file mode 100755
index 0000000..76fcbce
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnRouteType2Nlri.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.bgpio.protocol.evpn;
+
+import com.google.common.base.MoreObjects;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onlab.packet.MacAddress;
+import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.types.BgpEvpnEsi;
+import org.onosproject.bgpio.types.BgpEvpnLabel;
+import org.onosproject.bgpio.types.RouteDistinguisher;
+import org.onosproject.bgpio.util.Constants;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+
+public class BgpEvpnRouteType2Nlri implements BgpEvpnNlriData {
+
+    /*
+     * REFERENCE : RFC 7432 BGP MPLS-Based Ethernet VPN
+         +---------------------------------------+
+         | RD (8 octets) |
+         +---------------------------------------+
+         |Ethernet Segment Identifier (10 octets)|
+         +---------------------------------------+
+         | Ethernet Tag ID (4 octets) |
+         +---------------------------------------+
+         | MAC Address Length (1 octet) |
+         +---------------------------------------+
+         | MAC Address (6 octets) |
+         +---------------------------------------+
+         | IP Address Length (1 octet) |
+         +---------------------------------------+
+         | IP Address (0, 4, or 16 octets) |
+         +---------------------------------------+
+         | MPLS Label1 (3 octets) |
+         +---------------------------------------+
+         | MPLS Label2 (0 or 3 octets) |
+         +---------------------------------------+
+
+      Figure : A MAC/IP Advertisement route type specific EVPN NLRI
+
+     */
+
+    public static final short TYPE = Constants.BGP_EVPN_MAC_IP_ADVERTISEMENT;
+    protected static final Logger log = LoggerFactory.getLogger(BgpEvpnRouteType2Nlri.class);
+    // unit of length is bit
+    public static final short IPV4_ADDRESS_LENGTH = 32;
+    public static final short MAC_ADDRESS_LENGTH = 48;
+    private RouteDistinguisher rd;
+    private BgpEvpnEsi esi;
+    private int ethernetTagID;
+    private byte macAddressLength;
+    private MacAddress macAddress;
+    private byte ipAddressLength;
+    private InetAddress ipAddress;
+    private BgpEvpnLabel mplsLabel1;
+    private BgpEvpnLabel mplsLabel2;
+
+    /**
+     * Resets parameters.
+     */
+    public BgpEvpnRouteType2Nlri() {
+        this.rd = null;
+        this.esi = null;
+        this.ethernetTagID = 0;
+        this.macAddressLength = 0;
+        this.macAddress = null;
+        this.ipAddressLength = 0;
+        this.ipAddress = null;
+        this.mplsLabel1 = null;
+        this.mplsLabel2 = null;
+    }
+
+    /**
+     * Creates the Evpn route type 2 route.
+     *
+     * @param rd            route distinguisher
+     * @param esi           esi
+     * @param ethernetTagID ethernet tag id
+     * @param macAddress    mac
+     * @param ipAddress     ip
+     * @param mplsLabel1    label
+     * @param mplsLabel2    label
+     */
+    public BgpEvpnRouteType2Nlri(RouteDistinguisher rd,
+                                 BgpEvpnEsi esi,
+                                 int ethernetTagID, MacAddress macAddress,
+                                 InetAddress ipAddress, BgpEvpnLabel mplsLabel1,
+                                 BgpEvpnLabel mplsLabel2) {
+        this.rd = rd;
+        this.esi = esi;
+        this.ethernetTagID = ethernetTagID;
+        this.macAddressLength = MAC_ADDRESS_LENGTH;
+        this.macAddress = macAddress;
+        if (ipAddress != null) {
+            this.ipAddressLength = IPV4_ADDRESS_LENGTH;
+            this.ipAddress = ipAddress;
+        } else {
+            this.ipAddressLength = 0;
+            this.ipAddress = null;
+        }
+        this.mplsLabel1 = mplsLabel1;
+        this.mplsLabel2 = mplsLabel2;
+    }
+
+    /**
+     * Reads the Evpn type 2 attributes.
+     *
+     * @param cb channel buffer
+     * @return type2 route
+     * @throws BgpParseException parse exception
+     */
+    public static BgpEvpnRouteType2Nlri read(ChannelBuffer cb) throws BgpParseException {
+        if (cb.readableBytes() == 0) {
+            return null;
+        }
+        RouteDistinguisher rd = RouteDistinguisher.read(cb);
+        BgpEvpnEsi esi = BgpEvpnEsi.read(cb);
+        int ethernetTagID = cb.readInt();
+        byte macAddressLength = cb.readByte();
+        MacAddress macAddress = Validation.toMacAddress(macAddressLength / 8, cb);
+        byte ipAddressLength = cb.readByte();
+        InetAddress ipAddress = null;
+        if (ipAddressLength > 0) {
+            ipAddress = Validation.toInetAddress(ipAddressLength / 8, cb);
+        }
+        BgpEvpnLabel mplsLabel1 = BgpEvpnLabel.read(cb);
+        BgpEvpnLabel mplsLabel2 = null;
+        if (cb.readableBytes() > 0) {
+            mplsLabel2 = BgpEvpnLabel.read(cb);
+        }
+
+        return new BgpEvpnRouteType2Nlri(rd, esi, ethernetTagID, macAddress,
+                                         ipAddress, mplsLabel1,
+                                         mplsLabel2);
+    }
+
+    @Override
+    public int write(ChannelBuffer cb) {
+        int iLenStartIndex = cb.writerIndex();
+        cb.writeLong(rd.getRouteDistinguisher());
+        esi.write(cb);
+        cb.writeInt(ethernetTagID);
+        cb.writeByte(macAddressLength);
+        cb.writeBytes(macAddress.toBytes());
+        cb.writeByte(ipAddressLength);
+        if (ipAddressLength > 0) {
+            cb.writeBytes(ipAddress.getAddress());
+        }
+        mplsLabel1.write(cb);
+        if (mplsLabel2 != null) {
+            mplsLabel2.write(cb);
+        }
+        return cb.writerIndex() - iLenStartIndex;
+    }
+
+    /**
+     * Returns the rd.
+     *
+     * @return rd route distinguisher
+     */
+    public RouteDistinguisher getRouteDistinguisher() {
+        return rd;
+    }
+
+    /**
+     * Returns the esi.
+     *
+     * @return esi ethernet segment identifier
+     */
+    public BgpEvpnEsi getEthernetSegmentidentifier() {
+        return esi;
+    }
+
+    /**
+     * Returns the ethernet tag id.
+     *
+     * @return macAddress macadress
+     */
+    public int getEthernetTagID() {
+        return ethernetTagID;
+    }
+
+    public MacAddress getMacAddress() {
+        return macAddress;
+    }
+
+    /**
+     * Returns the ip address.
+     *
+     * @return ipAddress ipaddress
+     */
+    public InetAddress getIpAddress() {
+        return ipAddress;
+    }
+
+    /**
+     * Returns the mpls label.
+     *
+     * @return mplsLabel1 mpls label
+     */
+    public BgpEvpnLabel getMplsLable1() {
+        return mplsLabel1;
+    }
+
+    /**
+     * Returns the mpls label.
+     *
+     * @return mplsLabel2 mpls label
+     */
+    public BgpEvpnLabel getMplsLable2() {
+        return mplsLabel2;
+    }
+
+    /**
+     * Set the rd.
+     *
+     * @param rd route distinguisher
+     */
+    public void setRouteDistinguisher(RouteDistinguisher rd) {
+        this.rd = rd;
+    }
+
+    /**
+     * Set the ESI.
+     *
+     * @param esi esi
+     */
+    public void setEthernetSegmentidentifier(BgpEvpnEsi esi) {
+        this.esi = esi;
+    }
+
+    /**
+     * Set the ethernet tag id.
+     *
+     * @param ethernetTagID ethernet tag id.
+     */
+    public void setEthernetTagID(int ethernetTagID) {
+        this.ethernetTagID = ethernetTagID;
+    }
+
+    /**
+     * Set the mac address.
+     *
+     * @param macAddress mac
+     */
+    public void setMacAddress(MacAddress macAddress) {
+        this.macAddress = macAddress;
+    }
+
+    /**
+     * Set the ip address.
+     *
+     * @param ipAddress ip
+     */
+    public void setIpAddress(InetAddress ipAddress) {
+        this.ipAddress = ipAddress;
+    }
+
+    /**
+     * Set the mpls label.
+     *
+     * @param mplsLabel1 label
+     */
+    public void setMplsLable1(BgpEvpnLabel mplsLabel1) {
+        this.mplsLabel1 = mplsLabel1;
+    }
+
+    /**
+     * Set the mpls label.
+     *
+     * @param mplsLabel2 label
+     */
+    public void setMplsLable2(BgpEvpnLabel mplsLabel2) {
+        this.mplsLabel2 = mplsLabel2;
+    }
+
+    @Override
+    public BgpEvpnRouteType getType() {
+        return BgpEvpnRouteType.MAC_IP_ADVERTISEMENT;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass()).omitNullValues()
+                .add("rd ", rd)
+                .add("esi", esi)
+                .add("ethernetTagID", ethernetTagID)
+                .add("macAddressLength", macAddressLength)
+                .add("macAddress ", macAddress)
+                .add("ipAddressLength", ipAddressLength)
+                .add("ipAddress", ipAddress)
+                .add("mplsLabel1 ", mplsLabel1)
+                .add("mplsLabel2", mplsLabel2).toString();
+    }
+
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/package-info.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/package-info.java
new file mode 100755
index 0000000..69ee80b
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * BGP Protocol evpn components.
+ */
+package org.onosproject.bgpio.protocol.evpn;
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 9e6b86c..41ece38 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
@@ -322,6 +322,7 @@
         private boolean isFlowSpecCapabilityTlvSet = false;
         private boolean isVpnFlowSpecCapabilityTlvSet = false;
         private boolean isFlowSpecRpdCapabilityTlvSet = false;
+        private boolean isEvpnCapabilityTlvSet = false;
 
         LinkedList<BgpValueType> capabilityTlv = new LinkedList<>();
 
@@ -378,6 +379,12 @@
                 this.capabilityTlv.add(tlv);
             }
 
+            if (this.isEvpnCapabilityTlvSet) {
+                BgpValueType tlv;
+                tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_EVPN_VALUE,
+                        RES, Constants.SAFI_EVPN_VALUE);
+                this.capabilityTlv.add(tlv);
+            }
 
             return new BgpOpenMsgVer4(bgpMsgHeader, PACKET_VERSION, this.asNumber, holdTime, this.bgpId,
                        this.capabilityTlv);
@@ -445,6 +452,12 @@
             this.isFlowSpecRpdCapabilityTlvSet = isFlowSpecRpdCapabilityTlvSet;
             return this;
         }
+
+        @Override
+        public Builder setEvpnCapabilityTlv(boolean isEvpnCapabilitySet) {
+            this.isEvpnCapabilityTlvSet = isEvpnCapabilitySet;
+            return this;
+        }
     }
 
     @Override
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java
index 77c3b50..0c12525 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpUpdateMsgVer4.java
@@ -246,11 +246,17 @@
                     }
                 }
 
-                if ((afi == Constants.AFI_FLOWSPEC_VALUE) || (afi == Constants.AFI_VALUE)) {
+                if ((afi == Constants.AFI_FLOWSPEC_VALUE)
+                        || (afi == Constants.AFI_VALUE)) {
                     //unfeasible route length
                     cb.writeShort(0);
                 }
 
+                if ((afi == Constants.AFI_EVPN_VALUE)
+                        && (safi == Constants.SAFI_EVPN_VALUE)) {
+                    cb.writeShort(0);
+                }
+
             }
 
             if (message.bgpPathAttributes != null) {
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnEsi.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnEsi.java
new file mode 100755
index 0000000..b6816e8
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnEsi.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.bgpio.types;
+
+import java.util.Objects;
+import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.base.MoreObjects;
+
+/**
+ * Implementation of EthernetSegmentidentifier.
+ */
+public class BgpEvpnEsi
+        implements Comparable<BgpEvpnEsi> {
+
+    public static final int ESI_LENGTH = 10;
+    private byte[] ethernetSegmentidentifier;
+
+    /**
+     * Resets fields.
+     */
+    public BgpEvpnEsi() {
+        this.ethernetSegmentidentifier = null;
+    }
+
+    /**
+     * Constructor to initialize parameters.
+     *
+     * @param ethernetSegmentidentifier Ethernet Segment identifier
+     */
+    public BgpEvpnEsi(byte[] ethernetSegmentidentifier) {
+        this.ethernetSegmentidentifier = ethernetSegmentidentifier;
+    }
+
+    /**
+     * Reads Ethernet Segment identifier from channelBuffer.
+     *
+     * @param cb channelBuffer
+     * @return object of EthernetSegmentidentifier
+     */
+    public static BgpEvpnEsi read(ChannelBuffer cb) {
+        return new BgpEvpnEsi(cb.readBytes(10).array());
+    }
+
+    /**
+     * writes Ethernet Segment identifier into channelBuffer.
+     *
+     * @param cb channelBuffer
+     * @return length length of written data
+     */
+    public int write(ChannelBuffer cb) {
+        int iLenStartIndex = cb.writerIndex();
+        cb.writeBytes(ethernetSegmentidentifier);
+        return cb.writerIndex() - iLenStartIndex;
+    }
+
+    /**
+     * Returns Ethernet Segment identifier.
+     *
+     * @return Ethernet Segment identifier.
+     */
+    public byte[] getEthernetSegmentidentifier() {
+        return this.ethernetSegmentidentifier;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(ethernetSegmentidentifier);
+    };
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof BgpEvpnEsi) {
+            BgpEvpnEsi that = (BgpEvpnEsi) obj;
+            if (this.ethernetSegmentidentifier == that.ethernetSegmentidentifier) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("ethernetSegmentidentifier", ethernetSegmentidentifier)
+                .toString();
+    }
+
+    @Override
+    public int compareTo(BgpEvpnEsi rd) {
+        return 0;
+    }
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnLabel.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnLabel.java
new file mode 100755
index 0000000..60348ac
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnLabel.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.bgpio.types;
+
+import java.util.Objects;
+import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.base.MoreObjects;
+
+public class BgpEvpnLabel implements Comparable<BgpEvpnLabel> {
+
+    public static final int MPLS_LABEL_LENGTH = 3;
+    private byte[] mplsLabel;
+
+    /**
+     * Resets fields.
+     */
+    public BgpEvpnLabel() {
+        this.mplsLabel = null;
+    }
+
+    /**
+     * Constructor to initialize parameters.
+     *
+     * @param bgpEvpnLabel mpls label
+     */
+    public BgpEvpnLabel(byte[] bgpEvpnLabel) {
+        this.mplsLabel = bgpEvpnLabel;
+    }
+
+    /**
+     * Reads mpls label from channelBuffer.
+     *
+     * @param cb channelBuffer
+     * @return object of mpls label
+     */
+    public static BgpEvpnLabel read(ChannelBuffer cb) {
+        return new BgpEvpnLabel(cb.readBytes(3).array());
+    }
+
+    /**
+     * writes mpls label into channelBuffer.
+     *
+     * @param cb channelBuffer
+     * @return length length of written data
+     */
+    public int write(ChannelBuffer cb) {
+        int iLenStartIndex = cb.writerIndex();
+        cb.writeBytes(mplsLabel);
+        return cb.writerIndex() - iLenStartIndex;
+    }
+
+    /**
+     * Returns mpls label.
+     *
+     * @return mpls label
+     */
+    public byte[] getMplsLabel() {
+        return this.mplsLabel;
+    }
+
+    @Override
+    public int compareTo(BgpEvpnLabel mplsLabel) {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof BgpEvpnLabel) {
+
+            BgpEvpnLabel that = (BgpEvpnLabel) obj;
+
+            if (this.mplsLabel == that.mplsLabel) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(mplsLabel);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("mplsLabel", mplsLabel).toString();
+    }
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnPrefix.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnPrefix.java
new file mode 100755
index 0000000..142b12e
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnPrefix.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.bgpio.types;
+
+import org.onlab.packet.Ip4Address;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Represents the Evpn prefix.
+ */
+public class BgpEvpnPrefix {
+    private Ip4Address nextHop;
+    private RouteTarget rt;
+    BgpEvpnLabel label;
+
+    /**
+     * Constructor for initializing the evpn prefix.
+     *
+     * @param nextHop next hop
+     * @param rt      route target
+     * @param label   label
+     */
+    public BgpEvpnPrefix(Ip4Address nextHop, RouteTarget rt, BgpEvpnLabel label) {
+        this.nextHop = nextHop;
+        this.rt = rt;
+        this.label = label;
+    }
+
+    /**
+     * Constructor for initializing the evpn prefix.
+     *
+     * @param nextHop next hop
+     * @param label   label
+     */
+    public BgpEvpnPrefix(Ip4Address nextHop, BgpEvpnLabel label) {
+        this.nextHop = nextHop;
+        this.label = label;
+    }
+
+    /**
+     * Get next hop address.
+     *
+     * @return next hop
+     */
+    public Ip4Address getNextHop() {
+        return nextHop;
+    }
+
+    /**
+     * Get the route target.
+     *
+     * @return route target
+     */
+    public RouteTarget getRouteTarget() {
+        return rt;
+    }
+
+    /**
+     * Get the label.
+     *
+     * @return label
+     */
+    public BgpEvpnLabel getLabel() {
+        return label;
+
+    }
+
+    /**
+     * Set the next hop address.
+     *
+     * @param nextHop next hop
+     */
+    public void setNetHop(Ip4Address nextHop) {
+        this.nextHop = nextHop;
+    }
+
+    /**
+     * Set the route target.
+     *
+     * @param rt route target
+     */
+    public void setRouteTarget(RouteTarget rt) {
+        this.rt = rt;
+    }
+
+    /**
+     * Set the label.
+     *
+     * @param label label.
+     */
+    public void setLabel(BgpEvpnLabel label) {
+        this.label = label;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(nextHop,
+                            rt,
+                            label);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (this == other) {
+            return true;
+        }
+
+        if (!(other instanceof BgpEvpnPrefix)) {
+            return false;
+        }
+
+        BgpEvpnPrefix that = (BgpEvpnPrefix) other;
+
+        return Objects.equals(nextHop, that.nextHop)
+                && Objects.equals(rt, that.rt)
+                && Objects.equals(label, that.label);
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("next hop", nextHop)
+                .add("route target", rt)
+                .add("label", label)
+                .toString();
+    }
+}
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpExtendedCommunity.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpExtendedCommunity.java
index 7462bc8..941ed26 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpExtendedCommunity.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpExtendedCommunity.java
@@ -90,6 +90,11 @@
             while (actionBuf.readableBytes() > 0) {
                 short actionType = actionBuf.readShort();
                 switch (actionType) {
+                    case Constants.BGP_ROUTE_TARGET_AS:
+                    case Constants.BGP_ROUTE_TARGET_IP:
+                    case Constants.BGP_ROUTE_TARGET_LARGEAS:
+                        fsActionTlv = RouteTarget.read(actionType, actionBuf);
+                        break;
                     case Constants.BGP_FLOWSPEC_ACTION_TRAFFIC_ACTION:
                         fsActionTlv = BgpFsActionTrafficAction.read(actionBuf);
                         break;
@@ -102,7 +107,8 @@
                     case Constants.BGP_FLOWSPEC_ACTION_TRAFFIC_REDIRECT:
                         fsActionTlv = BgpFsActionReDirect.read(actionBuf);
                         break;
-                    default: log.debug("Other type Not Supported:" + actionType);
+                    default:
+                        log.debug("Other type Not Supported:" + actionType);
                         break;
                 }
                 if (fsActionTlv != null) {
@@ -156,7 +162,13 @@
 
         while (listIterator.hasNext()) {
             BgpValueType fsTlv = listIterator.next();
-            if (fsTlv.getType() == Constants.BGP_FLOWSPEC_ACTION_TRAFFIC_ACTION) {
+            if (fsTlv.getType() == Constants.BGP_ROUTE_TARGET_AS
+                    || fsTlv.getType() == Constants.BGP_ROUTE_TARGET_IP
+                    || fsTlv.getType() == Constants.BGP_ROUTE_TARGET_LARGEAS) {
+                RouteTarget routeTarget = (RouteTarget) fsTlv;
+                routeTarget.write(cb);
+            } else if (fsTlv.getType() == Constants
+                    .BGP_FLOWSPEC_ACTION_TRAFFIC_ACTION) {
                 BgpFsActionTrafficAction trafficAction = (BgpFsActionTrafficAction) fsTlv;
                 trafficAction.write(cb);
             } else if (fsTlv.getType() == Constants.BGP_FLOWSPEC_ACTION_TRAFFIC_MARKING) {
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpNlriType.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpNlriType.java
new file mode 100755
index 0000000..29b318d
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpNlriType.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.bgpio.types;
+
+public enum BgpNlriType {
+
+    /**
+     * Signifies Link State Nlri.
+     */
+    LINK_STATE,
+    /**
+     * Signifies Flow Spec Nlri.
+     */
+    FLOW_SPEC,
+    /**
+     * Signifies Evpn Nlri.
+     */
+    EVPN;
+
+}
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 328b623..106c4bb 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
@@ -16,25 +16,27 @@
 
 package org.onosproject.bgpio.types;
 
-import java.net.InetAddress;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-
+import com.google.common.base.MoreObjects;
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.onlab.packet.Ip4Address;
 import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.protocol.BgpEvpnNlri;
 import org.onosproject.bgpio.protocol.BgpLSNlri;
+import org.onosproject.bgpio.protocol.evpn.BgpEvpnNlriImpl;
+import org.onosproject.bgpio.protocol.evpn.BgpEvpnRouteType2Nlri;
 import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
-import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
-import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
+import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
+import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
 import org.onosproject.bgpio.util.Constants;
 import org.onosproject.bgpio.util.Validation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.MoreObjects;
+import java.net.InetAddress;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
 
 /*
  * Provides Implementation of MpReach Nlri BGP Path Attribute.
@@ -52,6 +54,7 @@
     private final byte safi;
     private final Ip4Address ipNextHop;
     private BgpFlowSpecNlri bgpFlowSpecNlri;
+    private List<BgpEvpnNlri> evpnNlri;
 
     /**
      * Constructor to initialize parameters.
@@ -71,6 +74,13 @@
         this.length = length;
     }
 
+    /**
+     * Constructor to initialize parameters.
+     *
+     * @param bgpFlowSpecNlri bgpFlowSpecNlri
+     * @param afi             afi
+     * @param safi            safi
+     */
     public MpReachNlri(BgpFlowSpecNlri bgpFlowSpecNlri, short afi, byte safi) {
         this.mpReachNlri = null;
         this.isMpReachNlri = true;
@@ -82,6 +92,24 @@
     }
 
     /**
+     * Constructor to initialize parameters.
+     *
+     * @param evpnNlri  evpnNlri
+     * @param afi       afi
+     * @param safi      safi
+     * @param ipNextHop IP Nexthop
+     */
+    public MpReachNlri(List<BgpEvpnNlri> evpnNlri, short afi, byte safi, Ip4Address ipNextHop) {
+        this.mpReachNlri = null;
+        this.length = 42;
+        this.ipNextHop = ipNextHop;
+        this.isMpReachNlri = true;
+        this.evpnNlri = evpnNlri;
+        this.afi = afi;
+        this.safi = safi;
+    }
+
+    /**
      * Returns whether MpReachNlri is present.
      *
      * @return whether MpReachNlri is present
@@ -118,6 +146,60 @@
     }
 
     /**
+     * Returns BGP Evpn info.
+     *
+     * @return BGP Evpn info
+     */
+    public List<BgpEvpnNlri> bgpEvpnNlri() {
+        return this.evpnNlri;
+    }
+
+    /**
+     * Returns afi.
+     *
+     * @return afi
+     */
+    public short getAfi() {
+        return this.afi;
+    }
+
+    /**
+     * Returns safi.
+     *
+     * @return safi
+     */
+    public byte getSafi() {
+        return this.safi();
+    }
+
+    /**
+     * Returns mpReachNlri details type.
+     *
+     * @return type
+     */
+    public BgpNlriType getNlriDetailsType() {
+        if ((this.afi == Constants.AFI_VALUE)
+                && (this.safi == Constants.SAFI_VALUE)
+                || (this.afi == Constants.AFI_VALUE)
+                && (this.safi == Constants.VPN_SAFI_VALUE)) {
+            return BgpNlriType.LINK_STATE;
+        }
+
+        if ((afi == Constants.AFI_FLOWSPEC_VALUE)
+                && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
+                || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
+            return BgpNlriType.FLOW_SPEC;
+        }
+
+        if ((afi == Constants.AFI_EVPN_VALUE)
+                && (safi == Constants.SAFI_EVPN_VALUE)) {
+            return BgpNlriType.EVPN;
+        }
+
+        return null;
+    }
+
+    /**
      * Reads from ChannelBuffer and parses MpReachNlri.
      *
      * @param cb channelBuffer
@@ -272,6 +354,29 @@
                 BgpFlowSpecNlri flowSpecDetails = new BgpFlowSpecNlri(flowSpecComponents);
                 flowSpecDetails.setRouteDistinguiher(routeDistinguisher);
                 return new MpReachNlri(flowSpecDetails, afi, safi);
+            } else if ((afi == Constants.AFI_EVPN_VALUE)
+                    && (safi == Constants.SAFI_EVPN_VALUE)) {
+
+                List<BgpEvpnNlri> eVpnComponents = null;
+
+                byte nextHopLen = tempCb.readByte();
+                InetAddress ipAddress = Validation.toInetAddress(nextHopLen,
+                                                                 tempCb);
+                if (ipAddress.isMulticastAddress()) {
+                    throw new BgpParseException("Multicast not supported");
+                }
+                ipNextHop = Ip4Address.valueOf(ipAddress);
+                byte reserved = tempCb.readByte();
+                while (tempCb.readableBytes() > 0) {
+                    BgpEvpnNlri eVpnComponent = BgpEvpnNlriImpl.read(tempCb);
+                    eVpnComponents = new LinkedList<>();
+                    eVpnComponents.add(eVpnComponent);
+                    log.info("=====evpn Component is {} ======", eVpnComponent);
+                }
+
+                return new MpReachNlri(eVpnComponents, afi, safi, ipNextHop);
+
+
             } else {
                 throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
             }
@@ -358,6 +463,48 @@
             int fsNlriLen = cb.writerIndex() - mpReachDataIndx;
             cb.setShort(mpReachDataIndx, (short) (fsNlriLen - 2));
 
+        } else if ((afi == Constants.AFI_EVPN_VALUE)
+                && (safi == Constants.SAFI_EVPN_VALUE)) {
+
+            cb.writeByte(FLAGS);
+            cb.writeByte(MPREACHNLRI_TYPE);
+
+            int mpReachDataIndex = cb.writerIndex();
+            cb.writeShort(0);
+            cb.writeShort(afi);
+            cb.writeByte(safi);
+            // ip address length
+            cb.writeByte(0x04);
+            cb.writeInt(ipNextHop.toInt());
+            //sub network points of attachment
+            cb.writeByte(0);
+
+            for (BgpEvpnNlri element : evpnNlri) {
+                short routeType = element.getType();
+                switch (routeType) {
+                    case Constants.BGP_EVPN_MAC_IP_ADVERTISEMENT:
+                        cb.writeByte(element.getType());
+                        int iSpecStartIndex = cb.writerIndex();
+                        cb.writeByte(0);
+                        BgpEvpnRouteType2Nlri macIpAdvNlri = (BgpEvpnRouteType2Nlri) element
+                                .getNlri();
+                        macIpAdvNlri.write(cb);
+                        cb.setByte(iSpecStartIndex, (byte) (cb.writerIndex()
+                                - iSpecStartIndex - 1));
+                        //ChannelBuffer temcb = cb.copy();
+                        break;
+                    case Constants.BGP_EVPN_ETHERNET_AUTO_DISCOVERY:
+                        break;
+                    case Constants.BGP_EVPN_INCLUSIVE_MULTICASE_ETHERNET:
+                        break;
+                    case Constants.BGP_EVPN_ETHERNET_SEGMENT:
+                        break;
+                    default:
+                        break;
+                }
+            }
+            int evpnNlriLen = cb.writerIndex() - mpReachDataIndex;
+            cb.setShort(mpReachDataIndex, (short) (evpnNlriLen - 2));
         }
 
         return cb.writerIndex() - iLenStartIndex;
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 9bc0189..e06fb0a 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
@@ -16,23 +16,25 @@
 
 package org.onosproject.bgpio.types;
 
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-
+import com.google.common.base.MoreObjects;
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.protocol.BgpEvpnNlri;
 import org.onosproject.bgpio.protocol.BgpLSNlri;
+import org.onosproject.bgpio.protocol.evpn.BgpEvpnNlriImpl;
+import org.onosproject.bgpio.protocol.evpn.BgpEvpnRouteType2Nlri;
 import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
+import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
-import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
 import org.onosproject.bgpio.util.Constants;
 import org.onosproject.bgpio.util.Validation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.MoreObjects;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
 
 /**
  * Provides Implementation of MpUnReach Nlri BGP Path Attribute.
@@ -49,6 +51,7 @@
     private final List<BgpLSNlri> mpUnReachNlri;
     private final int length;
     private BgpFlowSpecNlri bgpFlowSpecNlri;
+    private List<BgpEvpnNlri> evpnNlri;
 
     /**
      * Constructor to initialize parameters.
@@ -67,6 +70,13 @@
         this.length = length;
     }
 
+    /**
+     * Constructor to initialize parameters.
+     *
+     * @param bgpFlowSpecNlri bgpFlowSpecNlri
+     * @param afi             afi
+     * @param safi            safi
+     */
     public MpUnReachNlri(BgpFlowSpecNlri bgpFlowSpecNlri, short afi, byte safi) {
         this.mpUnReachNlri = null;
         this.isMpUnReachNlri = true;
@@ -77,6 +87,22 @@
     }
 
     /**
+     * Constructor to initialize parameters.
+     *
+     * @param evpnNlri evpnNlri
+     * @param afi      afi
+     * @param safi     safi
+     */
+    public MpUnReachNlri(List<BgpEvpnNlri> evpnNlri, short afi, byte safi) {
+        this.mpUnReachNlri = null;
+        this.isMpUnReachNlri = true;
+        this.length = 0;
+        this.evpnNlri = evpnNlri;
+        this.afi = afi;
+        this.safi = safi;
+    }
+
+    /**
      * Returns BGP flow specification info.
      *
      * @return BGP flow specification info
@@ -86,6 +112,60 @@
     }
 
     /**
+     * Returns BGP Evpn info.
+     *
+     * @return BGP Evpn info
+     */
+    public List<BgpEvpnNlri> bgpEvpnNlri() {
+        return this.evpnNlri;
+    }
+
+    /**
+     * Returns afi.
+     *
+     * @return afi
+     */
+    public short getAfi() {
+        return this.afi;
+    }
+
+    /**
+     * Returns safi.
+     *
+     * @return safi
+     */
+    public byte getSafi() {
+        return this.safi();
+    }
+
+    /**
+     * Returns mpUnReachNlri details type.
+     *
+     * @return type
+     */
+    public BgpNlriType getNlriDetailsType() {
+        if ((this.afi == Constants.AFI_VALUE)
+                && (this.safi == Constants.SAFI_VALUE)
+                || (this.afi == Constants.AFI_VALUE)
+                && (this.safi == Constants.VPN_SAFI_VALUE)) {
+            return BgpNlriType.LINK_STATE;
+        }
+
+        if ((afi == Constants.AFI_FLOWSPEC_VALUE)
+                && ((safi == Constants.SAFI_FLOWSPEC_VALUE)
+                || (safi == Constants.VPN_SAFI_FLOWSPEC_VALUE))) {
+            return BgpNlriType.FLOW_SPEC;
+        }
+
+        if ((afi == Constants.AFI_EVPN_VALUE)
+                && (safi == Constants.SAFI_EVPN_VALUE)) {
+            return BgpNlriType.EVPN;
+        }
+
+        return null;
+    }
+
+    /**
      * Reads from ChannelBuffer and parses MpUnReachNlri.
      *
      * @param cb ChannelBuffer
@@ -226,6 +306,17 @@
                 BgpFlowSpecNlri flowSpecDetails = new BgpFlowSpecNlri(flowSpecComponents);
                 flowSpecDetails.setRouteDistinguiher(routeDistinguisher);
                 return new MpUnReachNlri(flowSpecDetails, afi, safi);
+            } else if ((afi == Constants.AFI_EVPN_VALUE)
+                    && (safi == Constants.SAFI_EVPN_VALUE)) {
+                List<BgpEvpnNlri> eVpnComponents = null;
+                while (tempCb.readableBytes() > 0) {
+                    BgpEvpnNlri eVpnComponent = BgpEvpnNlriImpl.read(tempCb);
+                    eVpnComponents = new LinkedList<>();
+                    eVpnComponents.add(eVpnComponent);
+                    log.info("=====evpn Component is {} ======", eVpnComponent);
+                }
+
+                return new MpUnReachNlri(eVpnComponents, afi, safi);
             } else {
                 //TODO: check with the values got from capability
                 throw new BgpParseException("Not Supporting afi " + afi + "safi " + safi);
@@ -326,6 +417,45 @@
             }
             int fsNlriLen = cb.writerIndex() - mpUnReachIndx;
             cb.setShort(mpUnReachIndx, (short) (fsNlriLen - 2));
+        } else if ((afi == Constants.AFI_EVPN_VALUE)
+                && (safi == Constants.SAFI_EVPN_VALUE)) {
+
+            cb.writeByte(FLAGS);
+            cb.writeByte(MPUNREACHNLRI_TYPE);
+
+            int mpUnReachDataIndex = cb.writerIndex();
+            cb.writeShort(0);
+            cb.writeShort(afi);
+            cb.writeByte(safi);
+
+            for (BgpEvpnNlri element : evpnNlri) {
+                short routeType = element.getType();
+                switch (routeType) {
+                    case Constants.BGP_EVPN_MAC_IP_ADVERTISEMENT:
+                        cb.writeByte(element.getType());
+                        int iSpecStartIndex = cb.writerIndex();
+                        cb.writeByte(0);
+                        BgpEvpnRouteType2Nlri macIpAdvNlri =
+                                (BgpEvpnRouteType2Nlri) element
+                                        .getNlri();
+
+                        macIpAdvNlri.write(cb);
+                        cb.setByte(iSpecStartIndex, (short) (cb.writerIndex()
+                                - iSpecStartIndex - 1));
+                        break;
+                    case Constants.BGP_EVPN_ETHERNET_AUTO_DISCOVERY:
+                        break;
+                    case Constants.BGP_EVPN_INCLUSIVE_MULTICASE_ETHERNET:
+                        break;
+                    case Constants.BGP_EVPN_ETHERNET_SEGMENT:
+                        break;
+                    default:
+                        break;
+                }
+            }
+
+            int evpnNlriLen = cb.writerIndex() - mpUnReachDataIndex;
+            cb.setShort(mpUnReachDataIndex, (short) (evpnNlriLen - 2));
         }
 
         return cb.writerIndex() - iLenStartIndex;
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteTarget.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteTarget.java
new file mode 100755
index 0000000..5a009f9
--- /dev/null
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteTarget.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.bgpio.types;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Implementation of RouteTarget.
+ */
+public class RouteTarget implements BgpValueType {
+
+    /*
+     * Type 0x00: Local Administrator sub-field uses 2 octets with AS number and
+     * Assigned number uses 4 octests Type 0x01: Local Administrator sub-field
+     * uses 4 octets with IP address and Assigned number uses 2 octests Type
+     * 0x02: Local Administrator sub-field uses 4 octets with AS number and
+     * Assigned number uses 2 octests
+     */
+    private byte[] routeTarget;
+    private short type;
+
+    public enum RouteTargetype {
+
+        AS((short) 0x0002), IP((short) 0x0102), LARGEAS((short) 0x0202);
+        short value;
+
+        /**
+         * Assign val with the value as the tunnel type.
+         *
+         * @param val tunnel type
+         */
+        RouteTargetype(short val) {
+            value = val;
+        }
+
+        /**
+         * Returns value of route type.
+         *
+         * @return route type
+         */
+        public short getType() {
+            return value;
+        }
+    }
+
+    /**
+     * Resets fields.
+     */
+    public RouteTarget() {
+        this.type = 0;
+        this.routeTarget = null;
+    }
+
+    /**
+     * Constructor to initialize parameters.
+     *
+     * @param type        type
+     * @param routeTarget route target
+     */
+    public RouteTarget(short type, byte[] routeTarget) {
+        this.type = type;
+        this.routeTarget = routeTarget;
+    }
+
+    /**
+     * Reads route target from channelBuffer.
+     *
+     * @param type type
+     * @param cb   channelBuffer
+     * @return object of RouteTarget
+     */
+    public static RouteTarget read(short type, ChannelBuffer cb) {
+        return new RouteTarget(type, cb.readBytes(6).array());
+    }
+
+    /**
+     * Returns route target.
+     *
+     * @return route target
+     */
+    public byte[] getRouteTarget() {
+        return this.routeTarget;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof RouteTarget) {
+            RouteTarget that = (RouteTarget) obj;
+            if (this.type == that.type
+                    && this.routeTarget == that.routeTarget) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(routeTarget);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass()).add("type", type)
+                .add("routeTarget", routeTarget).toString();
+    }
+
+    @Override
+    public short getType() {
+        return type;
+    }
+
+    @Override
+    public int write(ChannelBuffer cb) {
+        int iLenStartIndex = cb.writerIndex();
+        cb.writeShort(type);
+        cb.writeBytes(routeTarget);
+        return cb.writerIndex() - iLenStartIndex;
+    }
+
+    @Override
+    public int compareTo(Object rd) {
+        return 0;
+    }
+}
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 43d31c5..1839a31 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
@@ -46,6 +46,9 @@
     public static final byte SAFI_FLOWSPEC_RPD_VALUE = (byte) 133;
     public static final byte VPN_SAFI_FLOWSPEC_RDP_VALUE = (byte) 134;
 
+    public static final short AFI_EVPN_VALUE = 25;
+    public static final byte SAFI_EVPN_VALUE = (byte) 70;
+
     public static final byte RPD_CAPABILITY_RECEIVE_VALUE = 0;
     public static final byte RPD_CAPABILITY_SEND_VALUE = 1;
     public static final byte RPD_CAPABILITY_SEND_RECEIVE_VALUE = 2;
@@ -73,6 +76,15 @@
     public static final byte BGP_FLOWSPEC_DSCP = 0x0b;
     public static final byte BGP_FLOWSPEC_FRAGMENT = 0x0c;
 
+    // for EVPN
+    public static final short BGP_ROUTE_TARGET_AS = (short) 0x0002;
+    public static final short BGP_ROUTE_TARGET_IP = (short) 0x0102;
+    public static final short BGP_ROUTE_TARGET_LARGEAS = (short) 0x0202;
+    public static final short BGP_EVPN_ETHERNET_AUTO_DISCOVERY = (short) 0x01;
+    public static final short BGP_EVPN_MAC_IP_ADVERTISEMENT = (short) 0x02;
+    public static final short BGP_EVPN_INCLUSIVE_MULTICASE_ETHERNET = (short) 0x03;
+    public static final short BGP_EVPN_ETHERNET_SEGMENT = (short) 0x04;
+
     public static final short BGP_FLOWSPEC_ACTION_TRAFFIC_RATE = (short) 0x8006;
     public static final short BGP_FLOWSPEC_ACTION_TRAFFIC_ACTION = (short) 0x8007;
     public static final short BGP_FLOWSPEC_ACTION_TRAFFIC_REDIRECT = (short) 0x8008;
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 93eb376..3f06487 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
@@ -24,6 +24,7 @@
 import org.jboss.netty.buffer.ChannelBuffers;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
 import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -151,7 +152,19 @@
         }
         return ipAddress;
     }
-
+    /**
+     * Convert byte array to MacAddress.
+     *
+     * @param length of MacAddress
+     * @param cb channelBuffer
+     * @return macAddress
+     */
+    public static MacAddress toMacAddress(int length, ChannelBuffer cb) {
+        byte[] address = new byte[length];
+        cb.readBytes(address, 0, length);
+        MacAddress macAddress = MacAddress.valueOf(address);
+        return macAddress;
+    }
     /**
      * Returns first bit in type flags.
      *
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 e2f83d4..036d8e6 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
@@ -677,6 +677,8 @@
 
         bgpId = Ip4Address.valueOf(bgpconfig.getRouterId()).toInt();
 
+        boolean evpnCapability = bgpconfig.getEvpnCapability();
+
         if (flowSpec == BgpCfg.FlowSpec.IPV4) {
             flowSpecStatus = true;
         } else if (flowSpec == BgpCfg.FlowSpec.VPNV4) {
@@ -692,6 +694,7 @@
                 .setLargeAsCapabilityTlv(bgpconfig.getLargeASCapability())
                 .setFlowSpecCapabilityTlv(flowSpecStatus)
                 .setVpnFlowSpecCapabilityTlv(vpnFlowSpecStatus)
+                .setEvpnCapabilityTlv(evpnCapability)
                 .setFlowSpecRpdCapabilityTlv(bgpconfig.flowSpecRpdCapability()).build();
         log.debug("Sending open message to {}", channel.getRemoteAddress());
         channel.write(Collections.singletonList(msg));
@@ -808,6 +811,9 @@
         boolean isMultiProtocolFlowSpecCapability = false;
         boolean isMultiProtocolVpnFlowSpecCapability = false;
         BgpCfg.FlowSpec flowSpec = h.bgpconfig.flowSpecCapability();
+        boolean isEvpnCapability = false;
+        boolean isEvpnCapabilityCfg = h.bgpconfig
+                .getEvpnCapability();
 
         if (flowSpec == BgpCfg.FlowSpec.IPV4) {
             isFlowSpecIpv4CapabilityCfg = true;
@@ -826,6 +832,10 @@
                     isMultiProtocolFlowSpecCapability = true;
                 }
 
+                if (Constants.SAFI_EVPN_VALUE == tempCapability.getSafi()) {
+                    isEvpnCapability = true;
+                }
+
                 if (Constants.VPN_SAFI_FLOWSPEC_VALUE == tempCapability.getSafi()) {
                     isMultiProtocolVpnFlowSpecCapability = true;
                 }
@@ -878,6 +888,15 @@
             }
         }
 
+        if (isEvpnCapabilityCfg) {
+            if (!isEvpnCapability) {
+                tempTlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_EVPN_VALUE,
+                        RES,
+                        Constants.SAFI_EVPN_VALUE);
+                unSupportedCapabilityTlv.add(tempTlv);
+            }
+        }
+
         if (isFlowSpecVpnv4CapabilityCfg) {
             if (!isMultiProtocolVpnFlowSpecCapability) {
                 tempTlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_VALUE,
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 f98f4bb..b15cfb8 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
@@ -15,13 +15,6 @@
  */
 package org.onosproject.bgp.controller.impl;
 
-import java.util.Iterator;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.List;
-import java.util.ArrayList;
-
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.IpAddress;
 import org.onosproject.bgp.controller.BgpCfg;
@@ -34,6 +27,13 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
 /**
  * Provides BGP configuration of this BGP speaker.
  */
@@ -60,6 +60,7 @@
     private BgpPeerManagerImpl peerManager;
     private BgpController bgpController;
     private boolean rpdCapability;
+    private boolean evpnCapability;
 
     /*
      * Constructor to initialize the values.
@@ -142,6 +143,16 @@
     }
 
     @Override
+    public boolean getEvpnCapability() {
+        return this.evpnCapability;
+    }
+
+    @Override
+    public void setEvpnCapability(boolean evpnCapability) {
+        this.evpnCapability = evpnCapability;
+    }
+
+    @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/BgpControllerImpl.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
index d9e0c2f..92ca7a4 100644
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
@@ -28,6 +28,7 @@
 import org.onosproject.bgp.controller.BgpNodeListener;
 import org.onosproject.bgp.controller.BgpPeer;
 import org.onosproject.bgp.controller.BgpPeerManager;
+import org.onosproject.bgp.controller.BgpRouteListener;
 import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.onosproject.bgpio.protocol.BgpMessage;
 import org.onosproject.bgpio.protocol.BgpUpdateMsg;
@@ -69,6 +70,7 @@
     private LinkedList<String> closedExceptionList = new LinkedList<String>();
     private Map<String, List<String>> activeSessionExceptionMap = new TreeMap<>();
     private Map<String, List<String>> closedSessionExceptionMap = new TreeMap<>();
+    protected Set<BgpRouteListener> bgpRouteListener = new CopyOnWriteArraySet<>();
 
     @Override
     public void activeSessionExceptionAdd(String peerId, String exception) {
@@ -111,6 +113,21 @@
         return closedSessionExceptionMap;
     }
 
+    @Override
+    public void addRouteListener(BgpRouteListener listener) {
+        this.bgpRouteListener.add(listener);
+    }
+
+    @Override
+    public void removeRouteListener(BgpRouteListener listener) {
+        this.bgpRouteListener.remove(listener);
+    }
+
+    @Override
+    public Set<BgpRouteListener> routeListener() {
+        return bgpRouteListener;
+    }
+
     @Activate
     public void activate() {
         this.ctrl.start();
@@ -163,46 +180,60 @@
         BgpPeer peer = getPeer(bgpId);
 
         switch (msg.getType()) {
-        case OPEN:
-            // TODO: Process Open message
-            break;
-        case KEEP_ALIVE:
-            // TODO: Process keepalive message
-            break;
-        case NOTIFICATION:
-            // TODO: Process notificatoin message
-            break;
-        case UPDATE:
-            BgpUpdateMsg updateMsg = (BgpUpdateMsg) msg;
-            List<BgpValueType> pathAttr = updateMsg.bgpPathAttributes().pathAttributes();
-            if (pathAttr == null) {
-               log.debug("llPathAttr is null, cannot process update message");
-               break;
-            }
-            Iterator<BgpValueType> listIterator = pathAttr.iterator();
-            boolean isLinkstate = false;
+            case OPEN:
+                // TODO: Process Open message
+                break;
+            case KEEP_ALIVE:
+                // TODO: Process keepalive message
+                break;
+            case NOTIFICATION:
+                // TODO: Process notificatoin message
+                break;
+            case UPDATE:
+                BgpUpdateMsg updateMsg = (BgpUpdateMsg) msg;
+                List<BgpValueType> pathAttr = updateMsg.bgpPathAttributes().pathAttributes();
+                if (pathAttr == null) {
+                    log.debug("llPathAttr is null, cannot process update message");
+                    break;
+                }
+                Iterator<BgpValueType> listIterator = pathAttr.iterator();
+                boolean isLinkstate = false;
+                boolean isEvpn = false;
 
-            while (listIterator.hasNext()) {
-                BgpValueType attr = listIterator.next();
-                if (attr instanceof MpReachNlri) {
-                    MpReachNlri mpReach = (MpReachNlri) attr;
-                    if (mpReach.bgpFlowSpecNlri() == null) {
-                        isLinkstate = true;
-                    }
-                } else if (attr instanceof MpUnReachNlri) {
-                    MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
-                    if (mpUnReach.bgpFlowSpecNlri() == null) {
-                        isLinkstate = true;
+                while (listIterator.hasNext()) {
+                    BgpValueType attr = listIterator.next();
+                    if (attr instanceof MpReachNlri) {
+                        MpReachNlri mpReach = (MpReachNlri) attr;
+                        if (mpReach.bgpFlowSpecNlri() == null
+                                && mpReach.bgpEvpnNlri() == null) {
+                            isLinkstate = true;
+                        }
+                        if (mpReach.bgpEvpnNlri() != null) {
+                            isEvpn = true;
+                        }
+                    } else if (attr instanceof MpUnReachNlri) {
+                        MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
+                        if (mpUnReach.bgpFlowSpecNlri() == null
+                                && mpUnReach.bgpEvpnNlri() == null) {
+                            isLinkstate = true;
+                        }
+                        if (mpUnReach.bgpEvpnNlri() != null) {
+                            isEvpn = true;
+                        }
                     }
                 }
-            }
-            if (isLinkstate) {
-                peer.buildAdjRibIn(pathAttr);
-            }
-            break;
-        default:
-            // TODO: Process other message
-            break;
+                if (isLinkstate) {
+                    peer.buildAdjRibIn(pathAttr);
+                }
+                if (isEvpn) {
+                    for (BgpRouteListener listener : bgpRouteListener) {
+                        listener.processRoute(bgpId, updateMsg);
+                    }
+                }
+                break;
+            default:
+                // TODO: Process other message
+                break;
         }
     }
 
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
index 34f4ec6..4dc8fee 100644
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
@@ -26,6 +26,7 @@
 import org.onosproject.bgp.controller.BgpPeer;
 import org.onosproject.bgp.controller.BgpSessionInfo;
 import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.protocol.BgpEvpnNlri;
 import org.onosproject.bgpio.protocol.BgpFactories;
 import org.onosproject.bgpio.protocol.BgpFactory;
 import org.onosproject.bgpio.protocol.BgpLSNlri;
@@ -36,8 +37,8 @@
 import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
 import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
-import org.onosproject.bgpio.types.AsPath;
 import org.onosproject.bgpio.types.As4Path;
+import org.onosproject.bgpio.types.AsPath;
 import org.onosproject.bgpio.types.BgpExtendedCommunity;
 import org.onosproject.bgpio.types.BgpValueType;
 import org.onosproject.bgpio.types.LocalPref;
@@ -46,8 +47,8 @@
 import org.onosproject.bgpio.types.MpUnReachNlri;
 import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
 import org.onosproject.bgpio.types.Origin;
-import org.onosproject.bgpio.types.attr.WideCommunity;
 import org.onosproject.bgpio.types.RpdCapabilityTlv;
+import org.onosproject.bgpio.types.attr.WideCommunity;
 import org.onosproject.bgpio.util.Constants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -256,6 +257,69 @@
     }
 
     @Override
+    public void updateEvpnNlri(FlowSpecOperation operType, IpAddress nextHop,
+                               List<BgpValueType> extcommunity,
+                               List<BgpEvpnNlri> evpnNlris) {
+        Preconditions.checkNotNull(operType, "Operation type cannot be null");
+        Preconditions.checkNotNull(evpnNlris, "Evpn nlri cannot be null");
+        sendEvpnUpdateMessageToPeer(operType, nextHop, extcommunity, evpnNlris);
+    }
+
+    private void sendEvpnUpdateMessageToPeer(FlowSpecOperation operType,
+                                             IpAddress nextHop,
+                                             List<BgpValueType> extcommunity,
+                                             List<BgpEvpnNlri> evpnNlris) {
+        List<BgpValueType> attributesList = new LinkedList<>();
+        byte sessionType = sessionInfo.isIbgpSession() ? (byte) 0 : (byte) 1;
+        short afi = Constants.AFI_EVPN_VALUE;
+        byte safi = Constants.SAFI_EVPN_VALUE;
+        boolean isEvpnCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
+                                                            afi, safi);
+        if (!isEvpnCapabilitySet) {
+            log.debug("Peer do not support BGP Evpn capability",
+                     channel.getRemoteAddress());
+            return;
+        }
+        attributesList.add(new Origin((byte) 0));
+
+        if (sessionType != 0) {
+            // EBGP
+            if (!bgpController.getConfig().getLargeASCapability()) {
+                List<Short> aspathSet = new ArrayList<>();
+                List<Short> aspathSeq = new ArrayList<>();
+                aspathSeq.add((short) bgpController.getConfig().getAsNumber());
+
+                AsPath asPath = new AsPath(aspathSet, aspathSeq);
+                attributesList.add(asPath);
+            } else {
+                List<Integer> aspathSet = new ArrayList<>();
+                List<Integer> aspathSeq = new ArrayList<>();
+                aspathSeq.add(bgpController.getConfig().getAsNumber());
+
+                As4Path as4Path = new As4Path(aspathSet, aspathSeq);
+                attributesList.add(as4Path);
+            }
+        } else {
+            attributesList.add(new AsPath());
+        }
+
+        if (!extcommunity.isEmpty()) {
+            attributesList.add(new BgpExtendedCommunity(extcommunity));
+        }
+        if (operType == FlowSpecOperation.ADD || operType == FlowSpecOperation.UPDATE) {
+            attributesList
+                    .add(new MpReachNlri(evpnNlris, afi, safi, nextHop.getIp4Address()));
+        } else if (operType == FlowSpecOperation.DELETE) {
+            attributesList.add(new MpUnReachNlri(evpnNlris, afi, safi));
+        }
+
+        BgpMessage msg = Controller.getBgpMessageFactory4()
+                .updateMessageBuilder().setBgpPathAttributes(attributesList)
+                .build();
+        channel.write(Collections.singletonList(msg));
+    }
+
+    @Override
     public void buildAdjRibIn(List<BgpValueType> pathAttr) throws BgpParseException {
         ListIterator<BgpValueType> iterator = pathAttr.listIterator();
         while (iterator.hasNext()) {
diff --git a/providers/bgp/BUCK b/providers/bgp/BUCK
index b5f516e..c6560b9 100644
--- a/providers/bgp/BUCK
+++ b/providers/bgp/BUCK
@@ -1,6 +1,7 @@
 BUNDLES = [
     '//providers/bgp/cfg:onos-providers-bgp-cfg',
     '//providers/bgp/topology:onos-providers-bgp-topology',
+    '//providers/bgp/route:onos-providers-bgp-route',
     '//providers/bgp/cli:onos-providers-bgp-cli',
     '//protocols/bgp/api:onos-protocols-bgp-api',
     '//protocols/bgp/ctl:onos-protocols-bgp-ctl',
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 f6583d4..23a4f5a 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
@@ -30,9 +30,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onosproject.net.config.Config.FieldPresence.MANDATORY;
 import static org.onosproject.net.config.Config.FieldPresence.OPTIONAL;
-import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Configuration object for BGP.
@@ -52,6 +52,7 @@
     public static final String LARGE_AS_CAPABILITY = "largeAsCapability";
     public static final String FLOW_SPEC_CAPABILITY = "flowSpecCapability";
     public static final String FLOW_SPEC_RPD_CAPABILITY = "flowSpecRpdCapability";
+    public static final String EVPN_CAPABILITY = "evpnCapability";
 
     public static final String BGP_PEER = "bgpPeer";
     public static final String PEER_IP = "peerIp";
@@ -78,12 +79,14 @@
         bgpConfig = bgpController.getConfig();
 
         fields = hasOnlyFields(ROUTER_ID, LOCAL_AS, MAX_SESSION, LS_CAPABILITY,
-                HOLD_TIME, LARGE_AS_CAPABILITY, FLOW_SPEC_CAPABILITY, FLOW_SPEC_RPD_CAPABILITY, BGP_PEER) &&
+                               HOLD_TIME, LARGE_AS_CAPABILITY, FLOW_SPEC_CAPABILITY,
+                               FLOW_SPEC_RPD_CAPABILITY, BGP_PEER, EVPN_CAPABILITY) &&
                 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);
+                isString(FLOW_SPEC_CAPABILITY, OPTIONAL) && isBoolean(FLOW_SPEC_RPD_CAPABILITY, OPTIONAL)
+                && isBoolean(EVPN_CAPABILITY, OPTIONAL);
 
         if (!fields) {
             return fields;
@@ -182,6 +185,15 @@
     }
 
     /**
+     * Returns evpn capability support from the configuration.
+     *
+     * @return evpn capability
+     */
+    public boolean evpnCapability() {
+        return Boolean.parseBoolean(get(EVPN_CAPABILITY, null));
+    }
+
+    /**
      * Validates the hold time value.
      *
      * @return true if valid else false
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 48eaa73..ad06c1d 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
@@ -127,6 +127,7 @@
         bgpConfig.setHoldTime(config.holdTime());
         bgpConfig.setMaxSession(config.maxSession());
         bgpConfig.setLargeASCapability(config.largeAsCapability());
+        bgpConfig.setEvpnCapability(config.evpnCapability());
 
         if (config.flowSpecCapability() == null) {
             bgpConfig.setFlowSpecCapability(BgpCfg.FlowSpec.NONE);
diff --git a/providers/bgp/pom.xml b/providers/bgp/pom.xml
index d2ef820..cd4c214 100644
--- a/providers/bgp/pom.xml
+++ b/providers/bgp/pom.xml
@@ -28,7 +28,8 @@
         <module>cfg</module>
         <module>app</module>
         <module>cli</module>
-  </modules>
+        <module>route</module>
+    </modules>
     <dependencies>
 
         <dependency>
diff --git a/providers/bgp/route/BUCK b/providers/bgp/route/BUCK
new file mode 100755
index 0000000..bf38465
--- /dev/null
+++ b/providers/bgp/route/BUCK
@@ -0,0 +1,16 @@
+COMPILE_DEPS = [
+  '//lib:CORE_DEPS',
+  '//protocols/bgp/api:onos-protocols-bgp-api',
+  '//protocols/bgp/bgpio:onos-protocols-bgp-bgpio',
+  '//incubator/store:onos-incubator-store',
+  '//incubator/api:onos-incubator-api',
+]
+
+TEST_DEPS = [
+  '//lib:TEST_ADAPTERS',
+]
+
+osgi_jar_with_tests(
+  deps = COMPILE_DEPS,
+  test_deps = TEST_DEPS,
+)
diff --git a/providers/bgp/route/pom.xml b/providers/bgp/route/pom.xml
new file mode 100755
index 0000000..e3bffcd
--- /dev/null
+++ b/providers/bgp/route/pom.xml
@@ -0,0 +1,50 @@
+<!--
+  ~ Copyright 2017-present Open Networking Foundation
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-bgp-providers</artifactId>
+        <version>1.11.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>onos-bgp-provider-route</artifactId>
+    <packaging>bundle</packaging>
+    <description>BGP route provider</description>
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-bgp-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-incubator-api</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+            <classifier>tests</classifier>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-bgp-api</artifactId>
+        </dependency>
+    </dependencies>
+</project>
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
new file mode 100755
index 0000000..81bd1d5
--- /dev/null
+++ b/providers/bgp/route/src/main/java/org/onosproject/provider/bgp/route/impl/BgpRouteProvider.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+
+package org.onosproject.provider.bgp.route.impl;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onosproject.bgp.controller.BgpController;
+import org.onosproject.bgp.controller.BgpId;
+import org.onosproject.bgp.controller.BgpPeer.FlowSpecOperation;
+import org.onosproject.bgp.controller.BgpRouteListener;
+import org.onosproject.bgpio.protocol.BgpEvpnNlri;
+import org.onosproject.bgpio.protocol.BgpUpdateMsg;
+import org.onosproject.bgpio.protocol.evpn.BgpEvpnNlriImpl;
+import org.onosproject.bgpio.protocol.evpn.BgpEvpnRouteType;
+import org.onosproject.bgpio.protocol.evpn.BgpEvpnRouteType2Nlri;
+import org.onosproject.bgpio.types.BgpEvpnEsi;
+import org.onosproject.bgpio.types.BgpEvpnLabel;
+import org.onosproject.bgpio.types.BgpExtendedCommunity;
+import org.onosproject.bgpio.types.BgpNlriType;
+import org.onosproject.bgpio.types.BgpValueType;
+import org.onosproject.bgpio.types.MpReachNlri;
+import org.onosproject.bgpio.types.MpUnReachNlri;
+import org.onosproject.bgpio.types.RouteDistinguisher;
+import org.onosproject.bgpio.types.RouteTarget;
+import org.onosproject.incubator.net.routing.EvpnRoute;
+import org.onosproject.incubator.net.routing.EvpnRoute.Source;
+import org.onosproject.incubator.net.routing.EvpnRouteAdminService;
+import org.onosproject.incubator.net.routing.EvpnRouteEvent;
+import org.onosproject.incubator.net.routing.EvpnRouteListener;
+import org.onosproject.incubator.net.routing.VpnRouteTarget;
+import org.onosproject.net.provider.AbstractProvider;
+import org.onosproject.net.provider.ProviderId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Provider which uses an BGP controller to update/delete route.
+ */
+@Component(immediate = true)
+public class BgpRouteProvider extends AbstractProvider {
+
+    /**
+     * Creates an instance of BGP route provider.
+     */
+    public BgpRouteProvider() {
+        super(new ProviderId("route",
+                             "org.onosproject.provider.bgp.route.impl"));
+    }
+
+    private static final Logger log = LoggerFactory
+            .getLogger(BgpRouteProvider.class);
+
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected BgpController controller;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected EvpnRouteAdminService evpnRouteAdminService;
+
+    private final InternalEvpnRouteListener routeListener = new
+            InternalEvpnRouteListener();
+    private final InternalBgpRouteListener bgpRouteListener = new
+            InternalBgpRouteListener();
+
+
+    @Activate
+    public void activate() {
+        controller.addRouteListener(bgpRouteListener);
+        evpnRouteAdminService.addListener(routeListener);
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        controller.removeRouteListener(bgpRouteListener);
+        evpnRouteAdminService.removeListener(routeListener);
+        log.info("Stopped");
+    }
+
+    /**
+     * Handles the bgp route update message.
+     *
+     * @param operationType operationType
+     * @param rdString      rd
+     * @param exportRtList  rt export
+     * @param nextHop       next hop
+     * @param macAddress    mac address
+     * @param ipAddress     ip address
+     * @param labelInt      label
+     */
+    private void sendUpdateMessage(FlowSpecOperation operationType,
+                                   String rdString,
+                                   List<VpnRouteTarget> exportRtList,
+                                   IpAddress nextHop,
+                                   MacAddress macAddress,
+                                   InetAddress ipAddress,
+                                   int labelInt) {
+        log.info("sendUpdateMessage 1");
+
+        List<BgpEvpnNlri> eVpnNlri = new ArrayList<BgpEvpnNlri>();
+        RouteDistinguisher rd = stringToRD(rdString);
+        BgpEvpnEsi esi = new BgpEvpnEsi(new byte[10]);
+        int ethernetTagID = 0;
+        BgpEvpnLabel mplsLabel1 = intToLabel(labelInt);
+        BgpEvpnLabel mplsLabel2 = null;
+
+        List<BgpValueType> extCom = new ArrayList<BgpValueType>();
+        if ((operationType == FlowSpecOperation.UPDATE)
+                && (!exportRtList.isEmpty())) {
+            for (VpnRouteTarget rt : exportRtList) {
+                RouteTarget rTarget = stringToRT(rt.getRouteTarget());
+                extCom.add(rTarget);
+            }
+        }
+        BgpEvpnRouteType2Nlri routeTypeSpec =
+                new BgpEvpnRouteType2Nlri(rd,
+                                          esi,
+                                          ethernetTagID,
+                                          macAddress,
+                                          ipAddress,
+                                          mplsLabel1,
+                                          mplsLabel2);
+        BgpEvpnNlri nlri = new BgpEvpnNlriImpl(BgpEvpnRouteType
+                                                       .MAC_IP_ADVERTISEMENT
+                                                       .getType(),
+                                               routeTypeSpec);
+        eVpnNlri.add(nlri);
+        log.info("sendUpdateMessage 2");
+        controller.getPeers().forEach(peer -> {
+            log.info("Send route update eVpnComponents {} to peer {}",
+                     eVpnNlri, peer);
+            peer.updateEvpnNlri(operationType, nextHop, extCom, eVpnNlri);
+        });
+
+    }
+
+    private static RouteDistinguisher stringToRD(String rdString) {
+        if (rdString.contains(":")) {
+            if ((rdString.indexOf(":") != 0)
+                    && (rdString.indexOf(":") != rdString.length() - 1)) {
+                String[] tem = rdString.split(":");
+                short as = (short) Integer.parseInt(tem[0]);
+                int assignednum = Integer.parseInt(tem[1]);
+                long rd = ((long) assignednum & 0xFFFFFFFFL)
+                        | (((long) as << 32) & 0xFFFFFFFF00000000L);
+                return new RouteDistinguisher(rd);
+            }
+        }
+        return null;
+
+    }
+
+    private static String rdToString(RouteDistinguisher rd) {
+        long rdLong = rd.getRouteDistinguisher();
+        int as = (int) ((rdLong & 0xFFFFFFFF00000000L) >> 32);
+        int assignednum = (int) (rdLong & 0xFFFFFFFFL);
+        String result = as + ":" + assignednum;
+        return result;
+    }
+
+    private static RouteTarget stringToRT(String rdString) {
+        if (rdString.contains(":")) {
+            if ((rdString.indexOf(":") != 0)
+                    && (rdString.indexOf(":") != rdString.length() - 1)) {
+                String[] tem = rdString.split(":");
+                short as = Short.parseShort(tem[0]);
+                int assignednum = Integer.parseInt(tem[1]);
+
+                byte[] rt = new byte[]{(byte) ((as >> 8) & 0xFF),
+                        (byte) (as & 0xFF),
+                        (byte) ((assignednum >> 24) & 0xFF),
+                        (byte) ((assignednum >> 16) & 0xFF),
+                        (byte) ((assignednum >> 8) & 0xFF),
+                        (byte) (assignednum & 0xFF)};
+                short type = 0x02;
+                return new RouteTarget(type, rt);
+            }
+        }
+        return null;
+
+    }
+
+    private static String rtToString(RouteTarget rt) {
+        byte[] b = rt.getRouteTarget();
+
+        int assignednum = b[5] & 0xFF | (b[4] & 0xFF) << 8 | (b[3] & 0xFF) << 16
+                | (b[2] & 0xFF) << 24;
+        short as = (short) (b[1] & 0xFF | (b[0] & 0xFF) << 8);
+        String result = as + ":" + assignednum;
+        return result;
+    }
+
+    private static BgpEvpnLabel intToLabel(int labelInt) {
+        byte[] label = new byte[]{(byte) ((labelInt >> 16) & 0xFF),
+                (byte) ((labelInt >> 8) & 0xFF),
+                (byte) (labelInt & 0xFF)};
+
+        return new BgpEvpnLabel(label);
+    }
+
+    private static int labelToInt(BgpEvpnLabel label) {
+        byte[] b = label.getMplsLabel();
+        return b[2] & 0xFF | (b[1] & 0xFF) << 8 | (b[0] & 0xFF) << 16;
+
+    }
+
+    private class InternalBgpRouteListener implements BgpRouteListener {
+
+        @Override
+        public void processRoute(BgpId bgpId, BgpUpdateMsg updateMsg) {
+            log.info("Evpn route event received from BGP protocol");
+            List<BgpValueType> pathAttr = updateMsg.bgpPathAttributes()
+                    .pathAttributes();
+            Iterator<BgpValueType> iterator = pathAttr.iterator();
+            RouteTarget rt = null;
+            List<VpnRouteTarget> exportRt = new LinkedList<>();
+            List<BgpEvpnNlri> evpnReachNlri = new LinkedList<>();
+            List<BgpEvpnNlri> evpnUnreachNlri = new LinkedList<>();
+
+            Ip4Address ipNextHop = null;
+            while (iterator.hasNext()) {
+                BgpValueType attr = iterator.next();
+                if (attr instanceof MpReachNlri) {
+                    MpReachNlri mpReachNlri = (MpReachNlri) attr;
+                    ipNextHop = mpReachNlri.nexthop4();
+                    if (mpReachNlri
+                            .getNlriDetailsType() == BgpNlriType.EVPN) {
+                        evpnReachNlri.addAll(mpReachNlri.bgpEvpnNlri());
+                    }
+
+                }
+                if (attr instanceof MpUnReachNlri) {
+                    MpUnReachNlri mpUnReachNlri = (MpUnReachNlri) attr;
+                    if (mpUnReachNlri
+                            .getNlriDetailsType() == BgpNlriType.EVPN) {
+                        evpnUnreachNlri.addAll(mpUnReachNlri.bgpEvpnNlri());
+                    }
+                }
+
+                if (attr instanceof BgpExtendedCommunity) {
+                    BgpExtendedCommunity extCom = (BgpExtendedCommunity) attr;
+                    Iterator<BgpValueType> extIte = extCom.fsActionTlv()
+                            .iterator();
+                    while (extIte.hasNext()) {
+                        BgpValueType extAttr = extIte.next();
+                        if (extAttr instanceof RouteTarget) {
+                            rt = (RouteTarget) extAttr;
+                            exportRt.add(VpnRouteTarget
+                                                 .routeTarget(rtToString(rt)));
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if ((!exportRt.isEmpty()) && (!evpnReachNlri.isEmpty())) {
+                for (BgpEvpnNlri nlri : evpnReachNlri) {
+                    if (nlri.getRouteType() == BgpEvpnRouteType
+                            .MAC_IP_ADVERTISEMENT) {
+                        BgpEvpnRouteType2Nlri macIpAdvNlri
+                                = (BgpEvpnRouteType2Nlri) nlri
+                                .getNlri();
+                        MacAddress macAddress = macIpAdvNlri.getMacAddress();
+                        Ip4Address ipAddress = Ip4Address
+                                .valueOf(macIpAdvNlri.getIpAddress());
+                        RouteDistinguisher rd = macIpAdvNlri
+                                .getRouteDistinguisher();
+                        BgpEvpnLabel label = macIpAdvNlri.getMplsLable1();
+                        log.info("Route Provider received bgp packet {} " +
+                                         "to route system.",
+                                 macIpAdvNlri.toString());
+                        // Add route to route system
+                        Source source = Source.REMOTE;
+                        EvpnRoute evpnRoute = new EvpnRoute(source,
+                                                            macAddress,
+                                                            IpPrefix.valueOf(ipAddress, 32),
+                                                            ipNextHop,
+                                                            rdToString(rd),
+                                                            null, //empty rt
+                                                            exportRt,
+                                                            labelToInt(label));
+
+                        evpnRouteAdminService.update(Collections
+                                                             .singleton(evpnRoute));
+                    }
+                }
+            }
+
+            if (!evpnUnreachNlri.isEmpty()) {
+                for (BgpEvpnNlri nlri : evpnUnreachNlri) {
+                    if (nlri.getRouteType() == BgpEvpnRouteType
+                            .MAC_IP_ADVERTISEMENT) {
+                        BgpEvpnRouteType2Nlri macIpAdvNlri
+                                = (BgpEvpnRouteType2Nlri) nlri
+                                .getNlri();
+                        MacAddress macAddress = macIpAdvNlri.getMacAddress();
+                        Ip4Address ipAddress = Ip4Address
+                                .valueOf(macIpAdvNlri.getIpAddress());
+                        RouteDistinguisher rd = macIpAdvNlri
+                                .getRouteDistinguisher();
+                        BgpEvpnLabel label = macIpAdvNlri.getMplsLable1();
+                        log.info("Route Provider received bgp packet {} " +
+                                         "and remove from route system.",
+                                 macIpAdvNlri.toString());
+                        // Delete route from route system
+                        Source source = Source.REMOTE;
+                        // For mpUnreachNlri, nexthop and rt is null
+                        EvpnRoute evpnRoute = new EvpnRoute(source,
+                                                            macAddress,
+                                                            IpPrefix.valueOf(ipAddress, 32),
+                                                            null,
+                                                            rdToString(rd),
+                                                            null,
+                                                            null,
+                                                            labelToInt(label));
+
+                        evpnRouteAdminService.withdraw(Collections
+                                                               .singleton(evpnRoute));
+                    }
+                }
+            }
+        }
+    }
+
+    private class InternalEvpnRouteListener implements EvpnRouteListener {
+
+        @Override
+        public void event(EvpnRouteEvent event) {
+            log.info("evpnroute event is received from evpn route manager");
+            FlowSpecOperation operationType = null;
+            EvpnRoute route = event.subject();
+            EvpnRoute evpnRoute = route;
+            log.info("Event received for public route {}", evpnRoute);
+            if (evpnRoute.source().equals(Source.REMOTE)) {
+                return;
+            }
+            switch (event.type()) {
+                case ROUTE_ADDED:
+                case ROUTE_UPDATED:
+                    log.info("route added");
+                    operationType = FlowSpecOperation.UPDATE;
+                    break;
+                case ROUTE_REMOVED:
+                    log.info("route deleted");
+                    operationType = FlowSpecOperation.DELETE;
+                    break;
+                default:
+                    break;
+            }
+
+            String rdString = evpnRoute.routeDistinguisher()
+                    .getRouteDistinguisher();
+            MacAddress macAddress = evpnRoute.prefixMac();
+            InetAddress inetAddress = evpnRoute.prefixIp().address().toInetAddress();
+            IpAddress nextHop = evpnRoute.ipNextHop();
+            List<VpnRouteTarget> exportRtList = evpnRoute
+                    .exportRouteTarget();
+            int labelInt = evpnRoute.label().getLabel();
+
+            sendUpdateMessage(operationType,
+                              rdString,
+                              exportRtList,
+                              nextHop,
+                              macAddress,
+                              inetAddress,
+                              labelInt);
+        }
+    }
+}
\ No newline at end of file
diff --git a/providers/bgp/route/src/main/java/org/onosproject/provider/bgp/route/impl/package-info.java b/providers/bgp/route/src/main/java/org/onosproject/provider/bgp/route/impl/package-info.java
new file mode 100755
index 0000000..97f14ab
--- /dev/null
+++ b/providers/bgp/route/src/main/java/org/onosproject/provider/bgp/route/impl/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * Provider that uses BGP controller as a means of infrastructure route exchange.
+ */
+package org.onosproject.provider.bgp.route.impl;
\ No newline at end of file
diff --git a/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpControllerAdapter.java b/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpControllerAdapter.java
index d8673cd..8102f17 100644
--- a/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpControllerAdapter.java
+++ b/providers/bgp/topology/src/test/java/org/onosproject/provider/bgp/topology/impl/BgpControllerAdapter.java
@@ -23,6 +23,7 @@
 import org.onosproject.bgp.controller.BgpNodeListener;
 import org.onosproject.bgp.controller.BgpPeer;
 import org.onosproject.bgp.controller.BgpPeerManager;
+import org.onosproject.bgp.controller.BgpRouteListener;
 import org.onosproject.bgpio.exceptions.BgpParseException;
 import org.onosproject.bgpio.protocol.BgpMessage;
 
@@ -130,6 +131,21 @@
     }
 
     @Override
+    public void addRouteListener(BgpRouteListener listener) {
+
+    }
+
+    @Override
+    public void removeRouteListener(BgpRouteListener listener) {
+
+    }
+
+    @Override
+    public Set<BgpRouteListener> routeListener() {
+        return null;
+    }
+
+    @Override
     public void addListener(BgpNodeListener listener) {
         // TODO Auto-generated method stub
     }