From 30fedc50beb5f250efc0e6ca11fb4a853dc79ae2 Mon Sep 17 00:00:00 2001 From: Mohammad Shahid Date: Wed, 9 Aug 2017 11:49:40 +0530 Subject: [PATCH] Adding BGP provider code to support EVPN Change-Id: Ic5508749b64a47a70f1aabd9324e9f89e85fa39f --- .../onosproject/bgp/controller/BgpCfg.java | 14 + .../bgp/controller/BgpController.java | 20 + .../onosproject/bgp/controller/BgpPeer.java | 16 +- .../bgp/controller/BgpRouteListener.java | 31 ++ .../bgpio/protocol/BgpEvpnNlri.java | 41 ++ .../bgpio/protocol/BgpOpenMsg.java | 10 + .../bgpio/protocol/evpn/BgpEvpnNlriData.java | 38 ++ .../bgpio/protocol/evpn/BgpEvpnNlriImpl.java | 172 ++++++++ .../bgpio/protocol/evpn/BgpEvpnRouteType.java | 44 ++ .../protocol/evpn/BgpEvpnRouteType2Nlri.java | 314 ++++++++++++++ .../bgpio/protocol/evpn/package-info.java | 20 + .../bgpio/protocol/ver4/BgpOpenMsgVer4.java | 13 + .../bgpio/protocol/ver4/BgpUpdateMsgVer4.java | 8 +- .../onosproject/bgpio/types/BgpEvpnEsi.java | 111 +++++ .../onosproject/bgpio/types/BgpEvpnLabel.java | 108 +++++ .../bgpio/types/BgpEvpnPrefix.java | 144 +++++++ .../bgpio/types/BgpExtendedCommunity.java | 16 +- .../onosproject/bgpio/types/BgpNlriType.java | 34 ++ .../onosproject/bgpio/types/MpReachNlri.java | 163 +++++++- .../bgpio/types/MpUnReachNlri.java | 142 ++++++- .../onosproject/bgpio/types/RouteTarget.java | 145 +++++++ .../org/onosproject/bgpio/util/Constants.java | 12 + .../onosproject/bgpio/util/Validation.java | 15 +- .../controller/impl/BgpChannelHandler.java | 19 + .../bgp/controller/impl/BgpConfig.java | 25 +- .../controller/impl/BgpControllerImpl.java | 105 +++-- .../bgp/controller/impl/BgpPeerImpl.java | 68 ++- providers/bgp/BUCK | 1 + .../provider/bgp/cfg/impl/BgpAppConfig.java | 18 +- .../provider/bgp/cfg/impl/BgpCfgProvider.java | 1 + providers/bgp/pom.xml | 3 +- providers/bgp/route/BUCK | 16 + providers/bgp/route/pom.xml | 50 +++ .../bgp/route/impl/BgpRouteProvider.java | 394 ++++++++++++++++++ .../provider/bgp/route/impl/package-info.java | 19 + .../topology/impl/BgpControllerAdapter.java | 16 + 36 files changed, 2297 insertions(+), 69 deletions(-) create mode 100755 protocols/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpRouteListener.java create mode 100755 protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BgpEvpnNlri.java create mode 100755 protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnNlriData.java create mode 100755 protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnNlriImpl.java create mode 100755 protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnRouteType.java create mode 100755 protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/BgpEvpnRouteType2Nlri.java create mode 100755 protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/evpn/package-info.java create mode 100755 protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnEsi.java create mode 100755 protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnLabel.java create mode 100755 protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnPrefix.java create mode 100755 protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpNlriType.java create mode 100755 protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteTarget.java create mode 100755 providers/bgp/route/BUCK create mode 100755 providers/bgp/route/pom.xml create mode 100755 providers/bgp/route/src/main/java/org/onosproject/provider/bgp/route/impl/BgpRouteProvider.java create mode 100755 providers/bgp/route/src/main/java/org/onosproject/provider/bgp/route/impl/package-info.java 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 992862c507..ca462ec4dc 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 @@ public interface BgpCfg { * @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 bb2b505539..b5cfe5a2fa 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 @@ public interface BgpController { * @return closedSessionMap */ Map> 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 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 0dbddeb767..ab26173060 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 @@ public interface BgpPeer { * @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 extcommunity, + List 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 0000000000..f2df135643 --- /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 0000000000..212b9213f2 --- /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 708bc068e6..4346b86b0c 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 @@ public interface BgpOpenMsg extends BgpMessage { */ 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 0000000000..e91e94aaaf --- /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 0000000000..cfe0530852 --- /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 0000000000..6b919c3929 --- /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 0000000000..76fcbce68d --- /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 0000000000..69ee80b906 --- /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 9e6b86c4d0..41ece38473 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 @@ public class BgpOpenMsgVer4 implements BgpOpenMsg { private boolean isFlowSpecCapabilityTlvSet = false; private boolean isVpnFlowSpecCapabilityTlvSet = false; private boolean isFlowSpecRpdCapabilityTlvSet = false; + private boolean isEvpnCapabilityTlvSet = false; LinkedList capabilityTlv = new LinkedList<>(); @@ -378,6 +379,12 @@ public class BgpOpenMsgVer4 implements BgpOpenMsg { 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 @@ public class BgpOpenMsgVer4 implements BgpOpenMsg { 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 77c3b50bd3..0c1252589c 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 @@ public class BgpUpdateMsgVer4 implements BgpUpdateMsg { } } - 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 0000000000..b6816e8870 --- /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 { + + 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 0000000000..60348ace07 --- /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 { + + 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 0000000000..142b12e541 --- /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 7462bc8a11..941ed267d6 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 @@ public class BgpExtendedCommunity implements BgpValueType { 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 @@ public class BgpExtendedCommunity implements BgpValueType { 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 @@ public class BgpExtendedCommunity implements BgpValueType { 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 0000000000..29b318d1c1 --- /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 328b6232c2..106c4bbd08 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 @@ public class MpReachNlri implements BgpValueType { private final byte safi; private final Ip4Address ipNextHop; private BgpFlowSpecNlri bgpFlowSpecNlri; + private List evpnNlri; /** * Constructor to initialize parameters. @@ -71,6 +74,13 @@ public class MpReachNlri implements BgpValueType { 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; @@ -81,6 +91,24 @@ public class MpReachNlri implements BgpValueType { this.safi = safi; } + /** + * Constructor to initialize parameters. + * + * @param evpnNlri evpnNlri + * @param afi afi + * @param safi safi + * @param ipNextHop IP Nexthop + */ + public MpReachNlri(List 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. * @@ -117,6 +145,60 @@ public class MpReachNlri implements BgpValueType { return this.bgpFlowSpecNlri; } + /** + * Returns BGP Evpn info. + * + * @return BGP Evpn info + */ + public List 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. * @@ -272,6 +354,29 @@ public class MpReachNlri implements BgpValueType { 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 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 @@ public class MpReachNlri implements BgpValueType { 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 9bc0189036..e06fb0a768 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 @@ public class MpUnReachNlri implements BgpValueType { private final List mpUnReachNlri; private final int length; private BgpFlowSpecNlri bgpFlowSpecNlri; + private List evpnNlri; /** * Constructor to initialize parameters. @@ -67,6 +70,13 @@ public class MpUnReachNlri implements BgpValueType { 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; @@ -76,6 +86,22 @@ public class MpUnReachNlri implements BgpValueType { this.safi = safi; } + /** + * Constructor to initialize parameters. + * + * @param evpnNlri evpnNlri + * @param afi afi + * @param safi safi + */ + public MpUnReachNlri(List 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. * @@ -85,6 +111,60 @@ public class MpUnReachNlri implements BgpValueType { return this.bgpFlowSpecNlri; } + /** + * Returns BGP Evpn info. + * + * @return BGP Evpn info + */ + public List 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. * @@ -226,6 +306,17 @@ public class MpUnReachNlri implements BgpValueType { 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 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 @@ public class MpUnReachNlri implements BgpValueType { } 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 0000000000..5a009f9fa4 --- /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 43d31c5573..1839a3126d 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 final class Constants { 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 final class Constants { 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 93eb37601a..3f06487590 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.ChannelBuffer; 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 @@ public class Validation { } 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 e2f83d49e6..036d8e6e43 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 @@ class BgpChannelHandler extends IdleStateAwareChannelHandler { 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 @@ class BgpChannelHandler extends IdleStateAwareChannelHandler { .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 @@ class BgpChannelHandler extends IdleStateAwareChannelHandler { 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 @@ class BgpChannelHandler extends IdleStateAwareChannelHandler { 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 @@ class BgpChannelHandler extends IdleStateAwareChannelHandler { } } + 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 f98f4bb959..b15cfb8720 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.onosproject.bgp.controller.impl.BgpControllerImpl.BgpPeerManagerImpl; 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 @@ public class BgpConfig implements BgpCfg { private BgpPeerManagerImpl peerManager; private BgpController bgpController; private boolean rpdCapability; + private boolean evpnCapability; /* * Constructor to initialize the values. @@ -141,6 +142,16 @@ public class BgpConfig implements BgpCfg { this.rpdCapability = rpdCapability; } + @Override + public boolean getEvpnCapability() { + return this.evpnCapability; + } + + @Override + public void setEvpnCapability(boolean evpnCapability) { + this.evpnCapability = evpnCapability; + } + @Override public String getRouterId() { if (this.routerId != null) { 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 d9e0c2f5e6..92ca7a46be 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.BgpLocalRib; 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 @@ public class BgpControllerImpl implements BgpController { private LinkedList closedExceptionList = new LinkedList(); private Map> activeSessionExceptionMap = new TreeMap<>(); private Map> closedSessionExceptionMap = new TreeMap<>(); + protected Set bgpRouteListener = new CopyOnWriteArraySet<>(); @Override public void activeSessionExceptionAdd(String peerId, String exception) { @@ -111,6 +113,21 @@ public class BgpControllerImpl implements BgpController { 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 routeListener() { + return bgpRouteListener; + } + @Activate public void activate() { this.ctrl.start(); @@ -163,46 +180,60 @@ public class BgpControllerImpl implements BgpController { 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 pathAttr = updateMsg.bgpPathAttributes().pathAttributes(); - if (pathAttr == null) { - log.debug("llPathAttr is null, cannot process update message"); - break; - } - Iterator 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 pathAttr = updateMsg.bgpPathAttributes().pathAttributes(); + if (pathAttr == null) { + log.debug("llPathAttr is null, cannot process update message"); + break; + } + Iterator 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 34f4ec6bf3..4dc8feebe8 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.BgpLocalRib; 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.BgpLinkLsNlriVer4; 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.MpReachNlri; 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; @@ -255,6 +256,69 @@ public class BgpPeerImpl implements BgpPeer { sendFlowSpecUpdateMessageToPeer(operType, routeKey, flowSpec, wideCommunity); } + @Override + public void updateEvpnNlri(FlowSpecOperation operType, IpAddress nextHop, + List extcommunity, + List 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 extcommunity, + List evpnNlris) { + List 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 aspathSet = new ArrayList<>(); + List aspathSeq = new ArrayList<>(); + aspathSeq.add((short) bgpController.getConfig().getAsNumber()); + + AsPath asPath = new AsPath(aspathSet, aspathSeq); + attributesList.add(asPath); + } else { + List aspathSet = new ArrayList<>(); + List 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 pathAttr) throws BgpParseException { ListIterator iterator = pathAttr.listIterator(); diff --git a/providers/bgp/BUCK b/providers/bgp/BUCK index b5f516ea35..c6560b9992 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 f6583d4334..23a4f5af62 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 org.slf4j.LoggerFactory; 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 class BgpAppConfig extends Config { 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 @@ public class BgpAppConfig extends Config { 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; @@ -181,6 +184,15 @@ public class BgpAppConfig extends Config { return true; } + /** + * 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. * 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 48eaa73793..ad06c1d8c4 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 @@ public class BgpCfgProvider extends AbstractProvider { 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 d2ef820916..cd4c2141b3 100644 --- a/providers/bgp/pom.xml +++ b/providers/bgp/pom.xml @@ -28,7 +28,8 @@ cfg app cli - + route + diff --git a/providers/bgp/route/BUCK b/providers/bgp/route/BUCK new file mode 100755 index 0000000000..bf384654b2 --- /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 0000000000..e3bffcdb77 --- /dev/null +++ b/providers/bgp/route/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + org.onosproject + onos-bgp-providers + 1.11.0-SNAPSHOT + + onos-bgp-provider-route + bundle + BGP route provider + + + org.onosproject + onos-bgp-api + + + org.onosproject + onos-incubator-api + ${project.version} + test + tests + + + org.easymock + easymock + test + + + org.onosproject + onos-bgp-api + + + 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 0000000000..81bd1d5882 --- /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 exportRtList, + IpAddress nextHop, + MacAddress macAddress, + InetAddress ipAddress, + int labelInt) { + log.info("sendUpdateMessage 1"); + + List eVpnNlri = new ArrayList(); + RouteDistinguisher rd = stringToRD(rdString); + BgpEvpnEsi esi = new BgpEvpnEsi(new byte[10]); + int ethernetTagID = 0; + BgpEvpnLabel mplsLabel1 = intToLabel(labelInt); + BgpEvpnLabel mplsLabel2 = null; + + List extCom = new ArrayList(); + 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 pathAttr = updateMsg.bgpPathAttributes() + .pathAttributes(); + Iterator iterator = pathAttr.iterator(); + RouteTarget rt = null; + List exportRt = new LinkedList<>(); + List evpnReachNlri = new LinkedList<>(); + List 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 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 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 0000000000..97f14ab4ca --- /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 d8673cd39a..8102f17691 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.BgpLocalRib; 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; @@ -129,6 +130,21 @@ public class BgpControllerAdapter implements BgpController { return null; } + @Override + public void addRouteListener(BgpRouteListener listener) { + + } + + @Override + public void removeRouteListener(BgpRouteListener listener) { + + } + + @Override + public Set routeListener() { + return null; + } + @Override public void addListener(BgpNodeListener listener) { // TODO Auto-generated method stub