Adding BGP provider code to support EVPN
Change-Id: Ic5508749b64a47a70f1aabd9324e9f89e85fa39f
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java
index e2f83d4..036d8e6 100644
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpChannelHandler.java
@@ -677,6 +677,8 @@
bgpId = Ip4Address.valueOf(bgpconfig.getRouterId()).toInt();
+ boolean evpnCapability = bgpconfig.getEvpnCapability();
+
if (flowSpec == BgpCfg.FlowSpec.IPV4) {
flowSpecStatus = true;
} else if (flowSpec == BgpCfg.FlowSpec.VPNV4) {
@@ -692,6 +694,7 @@
.setLargeAsCapabilityTlv(bgpconfig.getLargeASCapability())
.setFlowSpecCapabilityTlv(flowSpecStatus)
.setVpnFlowSpecCapabilityTlv(vpnFlowSpecStatus)
+ .setEvpnCapabilityTlv(evpnCapability)
.setFlowSpecRpdCapabilityTlv(bgpconfig.flowSpecRpdCapability()).build();
log.debug("Sending open message to {}", channel.getRemoteAddress());
channel.write(Collections.singletonList(msg));
@@ -808,6 +811,9 @@
boolean isMultiProtocolFlowSpecCapability = false;
boolean isMultiProtocolVpnFlowSpecCapability = false;
BgpCfg.FlowSpec flowSpec = h.bgpconfig.flowSpecCapability();
+ boolean isEvpnCapability = false;
+ boolean isEvpnCapabilityCfg = h.bgpconfig
+ .getEvpnCapability();
if (flowSpec == BgpCfg.FlowSpec.IPV4) {
isFlowSpecIpv4CapabilityCfg = true;
@@ -826,6 +832,10 @@
isMultiProtocolFlowSpecCapability = true;
}
+ if (Constants.SAFI_EVPN_VALUE == tempCapability.getSafi()) {
+ isEvpnCapability = true;
+ }
+
if (Constants.VPN_SAFI_FLOWSPEC_VALUE == tempCapability.getSafi()) {
isMultiProtocolVpnFlowSpecCapability = true;
}
@@ -878,6 +888,15 @@
}
}
+ if (isEvpnCapabilityCfg) {
+ if (!isEvpnCapability) {
+ tempTlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_EVPN_VALUE,
+ RES,
+ Constants.SAFI_EVPN_VALUE);
+ unSupportedCapabilityTlv.add(tempTlv);
+ }
+ }
+
if (isFlowSpecVpnv4CapabilityCfg) {
if (!isMultiProtocolVpnFlowSpecCapability) {
tempTlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_VALUE,
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java
index f98f4bb..b15cfb8 100644
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpConfig.java
@@ -15,13 +15,6 @@
*/
package org.onosproject.bgp.controller.impl;
-import java.util.Iterator;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.List;
-import java.util.ArrayList;
-
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onosproject.bgp.controller.BgpCfg;
@@ -34,6 +27,13 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
/**
* Provides BGP configuration of this BGP speaker.
*/
@@ -60,6 +60,7 @@
private BgpPeerManagerImpl peerManager;
private BgpController bgpController;
private boolean rpdCapability;
+ private boolean evpnCapability;
/*
* Constructor to initialize the values.
@@ -142,6 +143,16 @@
}
@Override
+ public boolean getEvpnCapability() {
+ return this.evpnCapability;
+ }
+
+ @Override
+ public void setEvpnCapability(boolean evpnCapability) {
+ this.evpnCapability = evpnCapability;
+ }
+
+ @Override
public String getRouterId() {
if (this.routerId != null) {
return this.routerId.toString();
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
index d9e0c2f..92ca7a4 100644
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpControllerImpl.java
@@ -28,6 +28,7 @@
import org.onosproject.bgp.controller.BgpNodeListener;
import org.onosproject.bgp.controller.BgpPeer;
import org.onosproject.bgp.controller.BgpPeerManager;
+import org.onosproject.bgp.controller.BgpRouteListener;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.protocol.BgpMessage;
import org.onosproject.bgpio.protocol.BgpUpdateMsg;
@@ -69,6 +70,7 @@
private LinkedList<String> closedExceptionList = new LinkedList<String>();
private Map<String, List<String>> activeSessionExceptionMap = new TreeMap<>();
private Map<String, List<String>> closedSessionExceptionMap = new TreeMap<>();
+ protected Set<BgpRouteListener> bgpRouteListener = new CopyOnWriteArraySet<>();
@Override
public void activeSessionExceptionAdd(String peerId, String exception) {
@@ -111,6 +113,21 @@
return closedSessionExceptionMap;
}
+ @Override
+ public void addRouteListener(BgpRouteListener listener) {
+ this.bgpRouteListener.add(listener);
+ }
+
+ @Override
+ public void removeRouteListener(BgpRouteListener listener) {
+ this.bgpRouteListener.remove(listener);
+ }
+
+ @Override
+ public Set<BgpRouteListener> routeListener() {
+ return bgpRouteListener;
+ }
+
@Activate
public void activate() {
this.ctrl.start();
@@ -163,46 +180,60 @@
BgpPeer peer = getPeer(bgpId);
switch (msg.getType()) {
- case OPEN:
- // TODO: Process Open message
- break;
- case KEEP_ALIVE:
- // TODO: Process keepalive message
- break;
- case NOTIFICATION:
- // TODO: Process notificatoin message
- break;
- case UPDATE:
- BgpUpdateMsg updateMsg = (BgpUpdateMsg) msg;
- List<BgpValueType> pathAttr = updateMsg.bgpPathAttributes().pathAttributes();
- if (pathAttr == null) {
- log.debug("llPathAttr is null, cannot process update message");
- break;
- }
- Iterator<BgpValueType> listIterator = pathAttr.iterator();
- boolean isLinkstate = false;
+ case OPEN:
+ // TODO: Process Open message
+ break;
+ case KEEP_ALIVE:
+ // TODO: Process keepalive message
+ break;
+ case NOTIFICATION:
+ // TODO: Process notificatoin message
+ break;
+ case UPDATE:
+ BgpUpdateMsg updateMsg = (BgpUpdateMsg) msg;
+ List<BgpValueType> pathAttr = updateMsg.bgpPathAttributes().pathAttributes();
+ if (pathAttr == null) {
+ log.debug("llPathAttr is null, cannot process update message");
+ break;
+ }
+ Iterator<BgpValueType> listIterator = pathAttr.iterator();
+ boolean isLinkstate = false;
+ boolean isEvpn = false;
- while (listIterator.hasNext()) {
- BgpValueType attr = listIterator.next();
- if (attr instanceof MpReachNlri) {
- MpReachNlri mpReach = (MpReachNlri) attr;
- if (mpReach.bgpFlowSpecNlri() == null) {
- isLinkstate = true;
- }
- } else if (attr instanceof MpUnReachNlri) {
- MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
- if (mpUnReach.bgpFlowSpecNlri() == null) {
- isLinkstate = true;
+ while (listIterator.hasNext()) {
+ BgpValueType attr = listIterator.next();
+ if (attr instanceof MpReachNlri) {
+ MpReachNlri mpReach = (MpReachNlri) attr;
+ if (mpReach.bgpFlowSpecNlri() == null
+ && mpReach.bgpEvpnNlri() == null) {
+ isLinkstate = true;
+ }
+ if (mpReach.bgpEvpnNlri() != null) {
+ isEvpn = true;
+ }
+ } else if (attr instanceof MpUnReachNlri) {
+ MpUnReachNlri mpUnReach = (MpUnReachNlri) attr;
+ if (mpUnReach.bgpFlowSpecNlri() == null
+ && mpUnReach.bgpEvpnNlri() == null) {
+ isLinkstate = true;
+ }
+ if (mpUnReach.bgpEvpnNlri() != null) {
+ isEvpn = true;
+ }
}
}
- }
- if (isLinkstate) {
- peer.buildAdjRibIn(pathAttr);
- }
- break;
- default:
- // TODO: Process other message
- break;
+ if (isLinkstate) {
+ peer.buildAdjRibIn(pathAttr);
+ }
+ if (isEvpn) {
+ for (BgpRouteListener listener : bgpRouteListener) {
+ listener.processRoute(bgpId, updateMsg);
+ }
+ }
+ break;
+ default:
+ // TODO: Process other message
+ break;
}
}
diff --git a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
index 34f4ec6..4dc8fee 100644
--- a/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
+++ b/protocols/bgp/ctl/src/main/java/org/onosproject/bgp/controller/impl/BgpPeerImpl.java
@@ -26,6 +26,7 @@
import org.onosproject.bgp.controller.BgpPeer;
import org.onosproject.bgp.controller.BgpSessionInfo;
import org.onosproject.bgpio.exceptions.BgpParseException;
+import org.onosproject.bgpio.protocol.BgpEvpnNlri;
import org.onosproject.bgpio.protocol.BgpFactories;
import org.onosproject.bgpio.protocol.BgpFactory;
import org.onosproject.bgpio.protocol.BgpLSNlri;
@@ -36,8 +37,8 @@
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpPrefixIPv4LSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
-import org.onosproject.bgpio.types.AsPath;
import org.onosproject.bgpio.types.As4Path;
+import org.onosproject.bgpio.types.AsPath;
import org.onosproject.bgpio.types.BgpExtendedCommunity;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.LocalPref;
@@ -46,8 +47,8 @@
import org.onosproject.bgpio.types.MpUnReachNlri;
import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
import org.onosproject.bgpio.types.Origin;
-import org.onosproject.bgpio.types.attr.WideCommunity;
import org.onosproject.bgpio.types.RpdCapabilityTlv;
+import org.onosproject.bgpio.types.attr.WideCommunity;
import org.onosproject.bgpio.util.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -256,6 +257,69 @@
}
@Override
+ public void updateEvpnNlri(FlowSpecOperation operType, IpAddress nextHop,
+ List<BgpValueType> extcommunity,
+ List<BgpEvpnNlri> evpnNlris) {
+ Preconditions.checkNotNull(operType, "Operation type cannot be null");
+ Preconditions.checkNotNull(evpnNlris, "Evpn nlri cannot be null");
+ sendEvpnUpdateMessageToPeer(operType, nextHop, extcommunity, evpnNlris);
+ }
+
+ private void sendEvpnUpdateMessageToPeer(FlowSpecOperation operType,
+ IpAddress nextHop,
+ List<BgpValueType> extcommunity,
+ List<BgpEvpnNlri> evpnNlris) {
+ List<BgpValueType> attributesList = new LinkedList<>();
+ byte sessionType = sessionInfo.isIbgpSession() ? (byte) 0 : (byte) 1;
+ short afi = Constants.AFI_EVPN_VALUE;
+ byte safi = Constants.SAFI_EVPN_VALUE;
+ boolean isEvpnCapabilitySet = isCapabilitySupported(MultiProtocolExtnCapabilityTlv.TYPE,
+ afi, safi);
+ if (!isEvpnCapabilitySet) {
+ log.debug("Peer do not support BGP Evpn capability",
+ channel.getRemoteAddress());
+ return;
+ }
+ attributesList.add(new Origin((byte) 0));
+
+ if (sessionType != 0) {
+ // EBGP
+ if (!bgpController.getConfig().getLargeASCapability()) {
+ List<Short> aspathSet = new ArrayList<>();
+ List<Short> aspathSeq = new ArrayList<>();
+ aspathSeq.add((short) bgpController.getConfig().getAsNumber());
+
+ AsPath asPath = new AsPath(aspathSet, aspathSeq);
+ attributesList.add(asPath);
+ } else {
+ List<Integer> aspathSet = new ArrayList<>();
+ List<Integer> aspathSeq = new ArrayList<>();
+ aspathSeq.add(bgpController.getConfig().getAsNumber());
+
+ As4Path as4Path = new As4Path(aspathSet, aspathSeq);
+ attributesList.add(as4Path);
+ }
+ } else {
+ attributesList.add(new AsPath());
+ }
+
+ if (!extcommunity.isEmpty()) {
+ attributesList.add(new BgpExtendedCommunity(extcommunity));
+ }
+ if (operType == FlowSpecOperation.ADD || operType == FlowSpecOperation.UPDATE) {
+ attributesList
+ .add(new MpReachNlri(evpnNlris, afi, safi, nextHop.getIp4Address()));
+ } else if (operType == FlowSpecOperation.DELETE) {
+ attributesList.add(new MpUnReachNlri(evpnNlris, afi, safi));
+ }
+
+ BgpMessage msg = Controller.getBgpMessageFactory4()
+ .updateMessageBuilder().setBgpPathAttributes(attributesList)
+ .build();
+ channel.write(Collections.singletonList(msg));
+ }
+
+ @Override
public void buildAdjRibIn(List<BgpValueType> pathAttr) throws BgpParseException {
ListIterator<BgpValueType> iterator = pathAttr.listIterator();
while (iterator.hasNext()) {