BGP Route policy distribution and flow spec
Change-Id: I8903efd225a24db6ccc85a4a3148a4dd6076e042
diff --git a/providers/bgpcep/flow/pom.xml b/providers/bgpcep/flow/pom.xml
index 5f9e2dd..4b8433b 100644
--- a/providers/bgpcep/flow/pom.xml
+++ b/providers/bgpcep/flow/pom.xml
@@ -35,5 +35,15 @@
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-bgp-flowapi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-bgp-ctl</artifactId>
+ <version>1.6.0-SNAPSHOT</version>
+ </dependency>
</dependencies>
</project>
diff --git a/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java b/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java
index 6f0f10a..182e3f8 100644
--- a/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java
+++ b/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java
@@ -18,8 +18,11 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -31,13 +34,63 @@
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MplsLabel;
import org.onosproject.bgp.controller.BgpController;
+import org.onosproject.bgp.controller.BgpId;
+import org.onosproject.bgp.controller.BgpPeer;
+import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecNlri;
+import org.onosproject.bgpio.protocol.flowspec.BgpFlowSpecRouteKey;
+import org.onosproject.bgpio.types.BgpFsActionReDirect;
+import org.onosproject.bgpio.types.BgpFsActionTrafficAction;
+import org.onosproject.bgpio.types.BgpFsActionTrafficMarking;
+import org.onosproject.bgpio.types.BgpFsActionTrafficRate;
+import org.onosproject.bgpio.types.BgpFsDestinationPortNum;
+import org.onosproject.bgpio.types.BgpFsDestinationPrefix;
+import org.onosproject.bgpio.types.BgpFsDscpValue;
+import org.onosproject.bgpio.types.BgpFsFragment;
+import org.onosproject.bgpio.types.BgpFsIcmpCode;
+import org.onosproject.bgpio.types.BgpFsIcmpType;
+import org.onosproject.bgpio.types.BgpFsIpProtocol;
+import org.onosproject.bgpio.types.BgpFsOperatorValue;
+import org.onosproject.bgpio.types.BgpFsPacketLength;
+import org.onosproject.bgpio.types.BgpFsPortNum;
+import org.onosproject.bgpio.types.BgpFsSourcePortNum;
+import org.onosproject.bgpio.types.BgpFsSourcePrefix;
+import org.onosproject.bgpio.types.BgpFsTcpFlags;
+import org.onosproject.bgpio.types.BgpValueType;
+import org.onosproject.bgpio.types.WideCommunityAttrHeader;
+import org.onosproject.bgpio.types.WideCommunityExcludeTarget;
+import org.onosproject.bgpio.types.WideCommunityInteger;
+import org.onosproject.bgpio.types.WideCommunityIpV4Neighbour;
+import org.onosproject.bgpio.types.WideCommunityParameter;
+import org.onosproject.bgpio.types.WideCommunityTarget;
+import org.onosproject.bgpio.types.attr.WideCommunity;
import org.onosproject.core.ApplicationId;
+import org.onosproject.flowapi.ExtDscpValue;
+import org.onosproject.flowapi.ExtFlowContainer;
+import org.onosproject.flowapi.ExtFlowTypes;
+import org.onosproject.flowapi.ExtFragment;
+import org.onosproject.flowapi.ExtIcmpCode;
+import org.onosproject.flowapi.ExtIcmpType;
+import org.onosproject.flowapi.ExtIpProtocol;
+import org.onosproject.flowapi.ExtKeyName;
+import org.onosproject.flowapi.ExtOperatorValue;
+import org.onosproject.flowapi.ExtPacketLength;
+import org.onosproject.flowapi.ExtPort;
+import org.onosproject.flowapi.ExtPrefix;
+import org.onosproject.flowapi.ExtTarget;
+import org.onosproject.flowapi.ExtTcpFlag;
+import org.onosproject.flowapi.ExtTrafficAction;
+import org.onosproject.flowapi.ExtTrafficMarking;
+import org.onosproject.flowapi.ExtTrafficRate;
+import org.onosproject.flowapi.ExtTrafficRedirect;
+import org.onosproject.flowapi.ExtWideCommunityInt;
import org.onosproject.incubator.net.resource.label.LabelResourceId;
import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.incubator.net.tunnel.TunnelService;
import org.onosproject.net.ConnectPoint;
+
+import org.onosproject.net.Annotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
@@ -56,12 +109,15 @@
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.FlowEntry.FlowEntryState;
import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.ExtensionCriterion;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.MetadataCriterion;
import org.onosproject.net.flow.criteria.MplsBosCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.TunnelIdCriterion;
+import org.onosproject.net.flow.instructions.ExtensionPropertyException;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.resource.ResourceService;
@@ -125,6 +181,7 @@
protected DeviceService deviceService;
private FlowRuleProviderService providerService;
+ public static final String FLOW_PEER = "flowPeer";
private PcepLabelObject labelObj;
public static final int OUT_LABEL_TYPE = 0;
public static final int IN_LABEL_TYPE = 1;
@@ -572,14 +629,19 @@
case ADD:
if (criteria == null) {
processRule(fbe.target(), PcepFlowType.ADD);
- flowEntries.add(new DefaultFlowEntry(fbe.target(), FlowEntryState.ADDED, 0, 0, 0));
+ } else {
+ handleMessage(fbe, BgpPeer.FlowSpecOperation.ADD, batch.deviceId());
}
+ flowEntries.add(new DefaultFlowEntry(fbe.target(), FlowEntryState.ADDED, 0, 0, 0));
break;
case REMOVE:
if (criteria == null) {
processRule(fbe.target(), PcepFlowType.REMOVE);
- flowEntries.add(new DefaultFlowEntry(fbe.target(), FlowEntryState.REMOVED, 0, 0, 0));
+ } else {
+ handleMessage(fbe, BgpPeer.FlowSpecOperation.DELETE, batch.deviceId());
}
+
+ flowEntries.add(new DefaultFlowEntry(fbe.target(), FlowEntryState.REMOVED, 0, 0, 0));
break;
default:
log.error("Unknown flow operation: {}", fbe);
@@ -590,4 +652,330 @@
providerService.batchOperationCompleted(batch.id(), status);
providerService.pushFlowMetrics(batch.deviceId(), flowEntries);
}
+
+ public void handleMessage(FlowRuleBatchEntry fbe, BgpPeer.FlowSpecOperation operType, DeviceId deviceId) {
+ Set<Criterion> set = fbe.target().selector().criteria();
+ Iterator iterator = set.iterator();
+ Criterion cr;
+
+ while (iterator.hasNext()) {
+ cr = (Criterion) iterator.next();
+
+ switch (cr.type()) {
+ case EXTENSION:
+ ExtensionCriterion extensionCriterion = (ExtensionCriterion) cr;
+ ExtensionSelector extension = extensionCriterion.extensionSelector();
+
+ ExtFlowContainer container = null;
+ List<ExtFlowTypes> bgpFlows = null;
+
+ try {
+ container = extension.getPropertyValue("container");
+ } catch (ExtensionPropertyException e) {
+ e.printStackTrace();
+ }
+
+ bgpFlows = container.container();
+ iterateAndSend(bgpFlows, operType, deviceId);
+ break;
+ default:
+ log.error("This flow type is not supported: {}", cr.type());
+ }
+ }
+ }
+
+ void iterateAndSend(List<ExtFlowTypes> bgpFlows, BgpPeer.FlowSpecOperation operType, DeviceId deviceId) {
+ ListIterator<ExtFlowTypes> iterator = bgpFlows.listIterator();
+ ExtFlowTypes flow;
+ ExtKeyName name = null;
+ ExtPrefix ipcSource = null;
+ ExtPrefix ipcDestination = null;
+ IpPrefix prefix = null;
+ ListIterator<IpPrefix> pfxItr = null;
+ ExtTrafficRate flowRate = null;
+ ExtTrafficAction flowAction = null;
+ ExtTrafficMarking flowMarking = null;
+ List<BgpValueType> flowSpecComponents = new ArrayList<>();
+ List<BgpFsOperatorValue> operatorValue;
+ BgpFlowSpecNlri flowSpec = new BgpFlowSpecNlri(flowSpecComponents);
+ BgpFsActionTrafficRate rate = null;
+ BgpFsActionTrafficAction action = null;
+ BgpFsActionReDirect redirection = null;
+ BgpFsActionTrafficMarking marking = null;
+ List<BgpValueType> flowSpecAction = new LinkedList<>();
+
+ ExtWideCommunityInt wcIntList = null;
+ ListIterator<Integer> wcItr = null;
+ WideCommunity wideCommunity = null;
+
+ int flags = 0;
+ int hopCount = 0;
+ int community = 0;
+ int contextAs = 0;
+ int localAs = 0;
+ WideCommunityInteger wCommInt;
+ WideCommunityParameter wCommParam = null;
+ List<BgpValueType> wcParam = new ArrayList<>();
+ WideCommunityTarget wcTarget = null;
+ WideCommunityExcludeTarget wcExcludeTarget = null;
+ WideCommunityAttrHeader wideCommunityHeader = null;
+
+ while (iterator.hasNext()) {
+ flow = iterator.next();
+ switch (flow.type()) {
+ case EXT_FLOW_RULE_KEY:
+ name = (ExtKeyName) flow;
+ break;
+ case IPV4_DST_PFX:
+ ipcDestination = (ExtPrefix) flow;
+ pfxItr = ipcDestination.prefix().listIterator();
+ prefix = pfxItr.next();
+ flowSpecComponents.add(new BgpFsDestinationPrefix((byte) prefix.prefixLength(),
+ prefix));
+ break;
+ case IPV4_SRC_PFX:
+ ipcSource = (ExtPrefix) flow;
+ pfxItr = ipcSource.prefix().listIterator();
+ prefix = pfxItr.next();
+ flowSpecComponents.add(new BgpFsSourcePrefix((byte) prefix.prefixLength(),
+ prefix));
+ break;
+ case IP_PROTO_LIST:
+ operatorValue = convert(((ExtIpProtocol) flow).ipProtocol());
+ flowSpecComponents.add(new BgpFsIpProtocol(operatorValue));
+ break;
+ case IN_PORT_LIST:
+ operatorValue = convert(((ExtPort) flow).port());
+ flowSpecComponents.add(new BgpFsPortNum(operatorValue));
+ break;
+ case DST_PORT_LIST:
+ operatorValue = convert(((ExtPort) flow).port());
+ flowSpecComponents.add(new BgpFsDestinationPortNum(operatorValue));
+ break;
+ case SRC_PORT_LIST:
+ operatorValue = convert(((ExtPort) flow).port());
+ flowSpecComponents.add(new BgpFsSourcePortNum(operatorValue));
+ break;
+ case ICMP_TYPE_LIST:
+ operatorValue = convert(((ExtIcmpType) flow).icmpType());
+ flowSpecComponents.add(new BgpFsIcmpType(operatorValue));
+ break;
+ case ICMP_CODE_LIST:
+ operatorValue = convert(((ExtIcmpCode) flow).icmpCode());
+ flowSpecComponents.add(new BgpFsIcmpCode(operatorValue));
+ break;
+ case TCP_FLAG_LIST:
+ operatorValue = convert(((ExtTcpFlag) flow).tcpFlag());
+ flowSpecComponents.add(new BgpFsTcpFlags(operatorValue));
+ break;
+ case PACKET_LENGTH_LIST:
+ operatorValue = convert(((ExtPacketLength) flow).packetLength());
+ flowSpecComponents.add(new BgpFsPacketLength(operatorValue));
+ break;
+ case DSCP_VALUE_LIST:
+ operatorValue = convert(((ExtDscpValue) flow).dscpValue());
+ flowSpecComponents.add(new BgpFsDscpValue(operatorValue));
+ break;
+ case FRAGMENT_LIST:
+ operatorValue = convert(((ExtFragment) flow).fragment());
+ flowSpecComponents.add(new BgpFsFragment(operatorValue));
+ break;
+ case TRAFFIC_RATE:
+ flowRate = (ExtTrafficRate) flow;
+ rate = new BgpFsActionTrafficRate(flowRate.asn(), flowRate.rate().floatValue());
+ flowSpecAction.add(rate);
+ flowSpec.setFsActionTlv(flowSpecAction);
+ break;
+ case TRAFFIC_ACTION:
+ flowAction = (ExtTrafficAction) flow;
+ byte[] byteAction = processTrafficAction((ExtTrafficAction) flow);
+ action = new BgpFsActionTrafficAction(byteAction);
+ flowSpecAction.add(action);
+ flowSpec.setFsActionTlv(flowSpecAction);
+ break;
+ case TRAFFIC_REDIRECT:
+ byte[] byteRedirect = processTrafficRedirect((ExtTrafficRedirect) flow);
+ redirection = new BgpFsActionReDirect(byteRedirect);
+ flowSpecAction.add(redirection);
+ flowSpec.setFsActionTlv(flowSpecAction);
+ break;
+ case TRAFFIC_MARKING:
+ byte[] byteMarking = new byte[6];
+ flowMarking = (ExtTrafficMarking) flow;
+ byteMarking[5] = flowMarking.marking();
+ marking = new BgpFsActionTrafficMarking(byteMarking);
+ flowSpecAction.add(marking);
+ flowSpec.setFsActionTlv(flowSpecAction);
+ break;
+ case WIDE_COMM_FLAGS:
+ wcIntList = (ExtWideCommunityInt) flow;
+ wcItr = wcIntList.communityInt().listIterator();
+ flags = wcItr.next().intValue();
+ break;
+ case WIDE_COMM_HOP_COUNT:
+ wcIntList = (ExtWideCommunityInt) flow;
+ wcItr = wcIntList.communityInt().listIterator();
+ hopCount = wcItr.next().intValue();
+ break;
+ case WIDE_COMM_COMMUNITY:
+ wcIntList = (ExtWideCommunityInt) flow;
+ wcItr = wcIntList.communityInt().listIterator();
+ community = wcItr.next().intValue();
+ break;
+ case WIDE_COMM_CONTEXT_AS:
+ wcIntList = (ExtWideCommunityInt) flow;
+ wcItr = wcIntList.communityInt().listIterator();
+ contextAs = wcItr.next().intValue();
+ break;
+ case WIDE_COMM_LOCAL_AS:
+ wcIntList = (ExtWideCommunityInt) flow;
+ wcItr = wcIntList.communityInt().listIterator();
+ localAs = wcItr.next().intValue();
+ break;
+ case WIDE_COMM_TARGET:
+ wcTarget = processWideCommTarget((ExtTarget) flow);
+ break;
+ case WIDE_COMM_EXT_TARGET:
+ wcExcludeTarget = processWideCommExcTarget((ExtTarget) flow);
+ break;
+ case WIDE_COMM_PARAMETER:
+ wcIntList = (ExtWideCommunityInt) flow;
+ wCommInt = new WideCommunityInteger(wcIntList.communityInt());
+ wcParam.add(wCommInt);
+ wCommParam = new WideCommunityParameter(wcParam);
+ break;
+ default:
+ log.error("error: this type is not supported");
+ break;
+ }
+ }
+
+ if ((flowAction != null) && flowAction.rpd()) {
+ wideCommunityHeader = new WideCommunityAttrHeader((byte) flags, (byte) hopCount, (short) 0);
+ wideCommunity = new WideCommunity(wideCommunityHeader, community, localAs, contextAs,
+ wcTarget, wcExcludeTarget, wCommParam);
+ }
+
+ if (name == null) {
+ log.error("BGP Flow key is required");
+ return;
+ }
+
+ BgpPeer peer = getPeer(deviceId);
+ if (peer != null) {
+ peer.updateFlowSpec(operType, new BgpFlowSpecRouteKey(name.keyName()), flowSpec, wideCommunity);
+ }
+ }
+
+ byte[] processTrafficAction(ExtTrafficAction flow) {
+ ExtTrafficAction flowAction = null;
+ byte[] byteAction = new byte[6];
+ byte actionByte = 0;
+ flowAction = (ExtTrafficAction) flow;
+ if (flowAction.terminal()) {
+ actionByte = (byte) (actionByte | (byte) 0x01);
+ }
+ if (flowAction.sample()) {
+ actionByte = (byte) (actionByte | (byte) 0x02);
+ }
+ if (flowAction.rpd()) {
+ actionByte = (byte) (actionByte | (byte) 0x04);
+ }
+ byteAction[5] = actionByte;
+ return byteAction;
+ }
+
+ byte[] processTrafficRedirect(ExtTrafficRedirect flow) {
+ ExtTrafficRedirect flowRedirect = null;
+ byte[] byteRedirect = new byte[6];
+ byte[] tmp;
+ int val;
+ flowRedirect = (ExtTrafficRedirect) flow;
+ val = Integer.decode(flowRedirect.redirect()).intValue();
+ tmp = intToByteStream(val);
+ for (int i = 0; i < tmp.length; i++) {
+ byteRedirect[i] = tmp [i];
+ }
+ return byteRedirect;
+ }
+
+ WideCommunityTarget processWideCommTarget(ExtTarget flow) {
+ ExtPrefix localSpeaker;
+ ExtPrefix remoteSpeaker;
+ ListIterator<IpPrefix> pfxItr = null;
+ ListIterator<IpPrefix> pfxItr1 = null;
+ List<BgpValueType> wcIpv4 = null;
+ ExtTarget target = flow;
+ WideCommunityIpV4Neighbour wcIpV4Neighbour = null;
+ WideCommunityTarget wcTarget = null;
+ localSpeaker = target.localSpeaker();
+ remoteSpeaker = target.remoteSpeaker();
+ wcIpV4Neighbour = new WideCommunityIpV4Neighbour();
+
+ pfxItr = localSpeaker.prefix().listIterator();
+ pfxItr1 = remoteSpeaker.prefix().listIterator();
+ while (pfxItr.hasNext()) {
+ wcIpV4Neighbour.add(pfxItr.next().address(), pfxItr1.next().address());
+ }
+
+ wcIpv4 = new ArrayList<>();
+ wcIpv4.add(wcIpV4Neighbour);
+ wcTarget = new WideCommunityTarget(wcIpv4);
+ return wcTarget;
+ }
+
+ WideCommunityExcludeTarget processWideCommExcTarget(ExtTarget flow) {
+ ExtPrefix localSpeaker;
+ ExtPrefix remoteSpeaker;
+ ListIterator<IpPrefix> pfxItr = null;
+ ListIterator<IpPrefix> pfxItr1 = null;
+ List<BgpValueType> wcIpv4 = null;
+ ExtTarget target = flow;
+ localSpeaker = target.localSpeaker();
+ remoteSpeaker = target.remoteSpeaker();
+ WideCommunityIpV4Neighbour wcIpV4Neighbour = null;
+ wcIpV4Neighbour = new WideCommunityIpV4Neighbour();
+ WideCommunityExcludeTarget wcExcludeTarget = null;
+
+ pfxItr = localSpeaker.prefix().listIterator();
+ pfxItr1 = remoteSpeaker.prefix().listIterator();
+ while (pfxItr.hasNext()) {
+ wcIpV4Neighbour.add(pfxItr.next().address(), pfxItr1.next().address());
+ }
+
+ wcIpv4 = new ArrayList<>();
+ wcIpv4.add(wcIpV4Neighbour);
+ wcExcludeTarget = new WideCommunityExcludeTarget(wcIpv4);
+ return wcExcludeTarget;
+ }
+
+ BgpPeer getPeer(DeviceId deviceId) {
+ Device d = deviceService.getDevice(deviceId);
+ Annotations a = d != null ? d.annotations() : null;
+ String ipAddress = a.value(FLOW_PEER);
+ BgpId bgpId = BgpId.bgpId(IpAddress.valueOf(ipAddress));
+ BgpPeer peer = bgpController.getPeer(bgpId);
+ return peer;
+ }
+
+ byte[] intToByteStream(int val) {
+ return new byte[] {
+ (byte) (val >>> 24),
+ (byte) (val >>> 16),
+ (byte) (val >>> 8),
+ (byte) val};
+ }
+
+ List<BgpFsOperatorValue> convert(List<ExtOperatorValue> opVal) {
+ List<BgpFsOperatorValue> list = new ArrayList();
+ BgpFsOperatorValue operatorValue;
+ Iterator iterator = opVal.iterator();
+ while (iterator.hasNext()) {
+ ExtOperatorValue element = (ExtOperatorValue) iterator.next();
+ operatorValue = new BgpFsOperatorValue(element.option(), element.value());
+ list.add(operatorValue);
+ }
+
+ return list;
+ }
}
diff --git a/providers/bgpcep/pom.xml b/providers/bgpcep/pom.xml
index 0bbecf3..01f8acf 100644
--- a/providers/bgpcep/pom.xml
+++ b/providers/bgpcep/pom.xml
@@ -32,16 +32,25 @@
</modules>
<dependencies>
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-pcep-controller-api</artifactId>
- <version>${project.version}</version>
- </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-bgp-flowapi</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-bgp-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-bgpio</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-pcep-controller-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-pcep-provider-tunnel</artifactId>
@@ -51,6 +60,22 @@
<groupId>org.onosproject</groupId>
<artifactId>onos-pcepio</artifactId>
<version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-junit</artifactId>
</dependency>
</dependencies>