Shashikanth VH

[ONOS-4240] Support wide community optional path attribute

Change-Id: I667cf229b02c8bcb0d4defd953bcde1595d03802
......@@ -32,6 +32,7 @@ import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv;
import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
import org.onosproject.bgpio.util.Validation;
import org.onosproject.bgpio.util.Constants;
import org.onosproject.bgpio.types.RpdCapabilityTlv;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -256,26 +257,36 @@ public class BgpOpenMsgVer4 implements BgpOpenMsg {
int as4Num = cb.readInt();
tlv = new FourOctetAsNumCapabilityTlv(as4Num);
break;
case RpdCapabilityTlv.TYPE:
log.debug("RpdCapability");
if (RpdCapabilityTlv.LENGTH != length) {
throw new BgpParseException("Invalid length received for RpdCapability.");
}
if (length > cb.readableBytes()) {
throw new BgpParseException("Four octet as num tlv length"
+ " is more than readableBytes.");
}
short rpdAfi = cb.readShort();
byte rpdAsafi = cb.readByte();
byte sendReceive = cb.readByte();
tlv = new RpdCapabilityTlv(sendReceive);
break;
case MultiProtocolExtnCapabilityTlv.TYPE:
log.debug("MultiProtocolExtnCapabilityTlv");
if (MultiProtocolExtnCapabilityTlv.LENGTH != length) {
throw new BgpParseException("Invalid length received for MultiProtocolExtnCapabilityTlv.");
}
if (length > cb.readableBytes()) {
throw new BgpParseException("BGP LS tlv length is more than readableBytes.");
}
short afi = cb.readShort();
byte res = cb.readByte();
byte safi = cb.readByte();
if ((afi == Constants.AFI_FLOWSPEC_RPD_VALUE) && (safi == Constants.SAFI_FLOWSPEC_RPD_VALUE)) {
if ((MultiProtocolExtnCapabilityTlv.LENGTH + 1) != length) {
throw new BgpParseException("Invalid length received for MultiProtocolExtnCapabilityTlv.");
}
tlv = new MultiProtocolExtnCapabilityTlv(afi, res, safi, cb.readByte());
} else {
if (MultiProtocolExtnCapabilityTlv.LENGTH != length) {
throw new BgpParseException("Invalid length received for MultiProtocolExtnCapabilityTlv.");
}
tlv = new MultiProtocolExtnCapabilityTlv(afi, res, safi);
}
break;
default:
log.debug("Warning: Unsupported TLV: " + type);
......@@ -358,9 +369,7 @@ public class BgpOpenMsgVer4 implements BgpOpenMsg {
if (this.isFlowSpecRpdCapabilityTlvSet) {
BgpValueType tlv;
tlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_RPD_VALUE,
RES, Constants.SAFI_FLOWSPEC_RPD_VALUE,
Constants.RPD_CAPABILITY_SEND_VALUE);
tlv = new RpdCapabilityTlv(Constants.RPD_CAPABILITY_SEND_VALUE);
this.capabilityTlv.add(tlv);
}
......
......@@ -36,6 +36,7 @@ import org.onosproject.bgpio.types.MpUnReachNlri;
import org.onosproject.bgpio.util.UnSupportedAttribute;
import org.onosproject.bgpio.util.Validation;
import org.onosproject.bgpio.util.Constants;
import org.onosproject.bgpio.types.attr.WideCommunity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -149,6 +150,9 @@ public class BgpPathAttributes {
case EXTENDED_COMMUNITY_TYPE:
pathAttribute = BgpExtendedCommunity.read(cb);
break;
case WideCommunity.TYPE:
pathAttribute = WideCommunity.read(cb);
break;
default:
//skip bytes for unsupported attribute types
UnSupportedAttribute.read(cb);
......@@ -214,6 +218,10 @@ public class BgpPathAttributes {
BgpExtendedCommunity extendedCommunity = (BgpExtendedCommunity) attr;
extendedCommunity.write(cb);
break;
case WideCommunity.TYPE:
WideCommunity wideCommunity = (WideCommunity) attr;
wideCommunity.write(cb);
break;
case MpReachNlri.MPREACHNLRI_TYPE:
MpReachNlri mpReach = (MpReachNlri) attr;
mpReach.write(cb);
......
......@@ -19,7 +19,6 @@ import com.google.common.base.MoreObjects;
import org.jboss.netty.buffer.ChannelBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.onosproject.bgpio.util.Constants;
import java.util.Objects;
......@@ -46,7 +45,6 @@ public class MultiProtocolExtnCapabilityTlv implements BgpValueType {
private final short afi;
private final byte res;
private final byte safi;
private final byte rpdSendReceive;
/**
* Constructor to initialize variables.
......@@ -58,24 +56,6 @@ public class MultiProtocolExtnCapabilityTlv implements BgpValueType {
this.afi = afi;
this.res = res;
this.safi = safi;
this.rpdSendReceive = Constants.RPD_CAPABILITY_SEND_VALUE;
}
/**
* Constructor to initialize variables.
* @param afi Address Family Identifiers
* @param res reserved field
* @param safi Subsequent Address Family Identifier
* @param rpdSendReceive indicates whether the sender is
(a) willing to receive Route Policies via BGP FLowSpec from its peer (value 1).
(b) would like to send Route Policies via BGP FLowSpec to its peer (value 2).
(c) both (value 3).
*/
public MultiProtocolExtnCapabilityTlv(short afi, byte res, byte safi, byte rpdSendReceive) {
this.afi = afi;
this.res = res;
this.safi = safi;
this.rpdSendReceive = rpdSendReceive;
}
/**
......@@ -140,16 +120,9 @@ public class MultiProtocolExtnCapabilityTlv implements BgpValueType {
@Override
public int write(ChannelBuffer cb) {
boolean isFsRpd = false;
int iLenStartIndex = cb.writerIndex();
cb.writeByte(TYPE);
if ((afi == Constants.AFI_FLOWSPEC_RPD_VALUE) && (safi == Constants.SAFI_FLOWSPEC_RPD_VALUE)) {
cb.writeByte(LENGTH + 1);
isFsRpd = true;
} else {
cb.writeByte(LENGTH);
}
// write afi
cb.writeShort(afi);
......@@ -160,11 +133,6 @@ public class MultiProtocolExtnCapabilityTlv implements BgpValueType {
// write safi
cb.writeByte(safi);
if (isFsRpd) {
// write Send/Receive (1 octet)
cb.writeByte(rpdSendReceive);
}
return cb.writerIndex() - iLenStartIndex;
}
......@@ -177,10 +145,6 @@ public class MultiProtocolExtnCapabilityTlv implements BgpValueType {
short afi = cb.readShort();
byte res = cb.readByte();
byte safi = cb.readByte();
if ((afi == Constants.AFI_FLOWSPEC_RPD_VALUE) && (safi == Constants.SAFI_FLOWSPEC_RPD_VALUE)) {
return new MultiProtocolExtnCapabilityTlv(afi, res, safi, cb.readByte());
}
return new MultiProtocolExtnCapabilityTlv(afi, res, safi);
}
......
/*
* Copyright 2016-present Open Networking Laboratory
*
* 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 org.onosproject.bgpio.util.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.MoreObjects;
/**
* Provides implementation of BGP route policy distribution capability tlv.
*/
public class RpdCapabilityTlv implements BgpValueType {
protected static final Logger log = LoggerFactory
.getLogger(RpdCapabilityTlv.class);
public static final byte TYPE = (byte) 129;
public static final byte LENGTH = 4;
private short afi = Constants.AFI_FLOWSPEC_RPD_VALUE;
private byte sAfi = Constants.SAFI_FLOWSPEC_RPD_VALUE;
private final byte sendReceive;
/**
* Creates instance of route policy distribution capability.
* @param sendReceive value indicate wherether flow route is only for receive or send or both.
*/
public RpdCapabilityTlv(byte sendReceive) {
this.sendReceive = sendReceive;
}
/**
* Creates instance of RpdCapabilityTlv.
* @param sendReceive value indicate wherether flow route is only for receive or send or both.
* @return object of RpdCapabilityTlv
*/
public static RpdCapabilityTlv of(final byte sendReceive) {
return new RpdCapabilityTlv(sendReceive);
}
/**
* Returns value of send receive field of route policy distribution capability.
* @return send receive value of route policy distribution capability
*/
public byte sendReceive() {
return sendReceive;
}
@Override
public short getType() {
return TYPE;
}
@Override
public int hashCode() {
return Objects.hash(sendReceive);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof RpdCapabilityTlv) {
RpdCapabilityTlv other = (RpdCapabilityTlv) obj;
return Objects.equals(sendReceive, other.sendReceive);
}
return false;
}
@Override
public int write(ChannelBuffer cb) {
int iLenStartIndex = cb.writerIndex();
cb.writeByte(TYPE);
cb.writeByte(LENGTH);
cb.writeShort(afi);
cb.writeByte(sAfi);
cb.writeByte(sendReceive);
return cb.writerIndex() - iLenStartIndex;
}
/**
* Reads the channel buffer and returns object of RpdCapabilityTlv.
* @param cb type of channel buffer
* @return object of RpdCapabilityTlv
*/
public static RpdCapabilityTlv read(ChannelBuffer cb) {
short afi = cb.readShort();
byte sAfi = cb.readByte();
return RpdCapabilityTlv.of(cb.readByte());
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("Type", TYPE)
.add("Length", LENGTH)
.add("afi", afi)
.add("safi", sAfi)
.add("sendReceive", sendReceive).toString();
}
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
}
......@@ -43,8 +43,8 @@ public final class Constants {
/* TODO: The Capability Code
for this capability is to be specified by the IANA.*/
public static final short AFI_FLOWSPEC_RPD_VALUE = 1;
public static final byte SAFI_FLOWSPEC_RPD_VALUE = (byte) 200;
public static final byte VPN_SAFI_FLOWSPEC_RDP_VALUE = (byte) 201;
public static final byte SAFI_FLOWSPEC_RPD_VALUE = (byte) 133;
public static final byte VPN_SAFI_FLOWSPEC_RDP_VALUE = (byte) 134;
public static final byte RPD_CAPABILITY_RECEIVE_VALUE = 0;
public static final byte RPD_CAPABILITY_SEND_VALUE = 1;
......
......@@ -316,11 +316,12 @@ public class BgpOpenMsgTest {
// OPEN Message with capabilities.
byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00, 0x38, 0x01, 0x04, 0x00,
0x64, 0x00, (byte) 0xb4, (byte) 0xc0, (byte) 0xa8, 0x07, 0x35, 0x1b, 0x02, 0x19,
0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x01, 0x04, 0x40, 0x04, 0x00, 0x47, 0x01,
0x04, 0x00, 0x01, 0x00, (byte) 0x85, 0x01, 0x05, 0x00, 0x01, 0x00, (byte) 0xc8,
0x00 }; // Four Octet AS Number-CAPABILITY-TLV
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
0x00, 0x3d, 0x01, 0x04, 0x00, (byte) 0xc8, 0x00, (byte) 0xb4, (byte) 0xc0,
(byte) 0xa8, 0x07, 0x35, 0x20, 0x02, 0x1e, 0x01,
0x04, 00, 0x01, 0x00, 0x01, 0x41, 0x04, 0x00, 0x00, 0x00, (byte) 0xc8, 0x01,
0x04, 0x40, 0x04, 0x00, 0x47, 0x01, 0x04, 0x00, 0x01, 0x00, (byte) 0x85,
(byte) 0x81, 0x04, 0x00, 0x01, (byte) 0x85, 0x01 }; //RPD capability
byte[] testOpenMsg;
ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
......@@ -353,11 +354,12 @@ public class BgpOpenMsgTest {
// OPEN Message with invalid message type.
byte[] openMsg = new byte[] {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x00, 0x38, 0x01, 0x04, 0x00,
0x64, 0x00, (byte) 0xb4, (byte) 0xc0, (byte) 0xa8, 0x07, 0x35, 0x1b, 0x02, 0x19,
0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x01, 0x04, 0x40, 0x04, 0x00, 0x47, 0x01,
0x04, 0x00, 0x01, 0x00, (byte) 0x85, 0x01, 0x04, 0x00, 0x01, 0x00, (byte) 0xc8,
0x00 };
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
0x00, 0x3d, 0x01, 0x04, 0x00, (byte) 0xc8, 0x00, (byte) 0xb4, (byte) 0xc0,
(byte) 0xa8, 0x07, 0x35, 0x20, 0x02, 0x1e, 0x01, 0x04, 00, 0x01, 0x00, 0x01, 0x41,
0x04, 0x00, 0x00, 0x00, (byte) 0xc8, 0x01, 0x04, 0x40, 0x04, 0x00,
0x47, 0x01, 0x04, 0x00, 0x01, 0x00, (byte) 0x85,
(byte) 0x81, 0x05, 0x00, 0x01, (byte) 0x85, 0x01 }; //RPD capability
ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
buffer.writeBytes(openMsg);
......
......@@ -44,6 +44,7 @@ import org.onosproject.bgpio.types.BgpErrorType;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv;
import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
import org.onosproject.bgpio.types.RpdCapabilityTlv;
import org.onosproject.bgpio.util.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -784,7 +785,9 @@ class BgpChannelHandler extends IdleStateAwareChannelHandler {
log.debug("capabilityValidation");
boolean isFourOctetCapabilityExits = false;
boolean isRpdCapabilityExits = false;
int capAsNum = 0;
byte sendReceive = 0;
List<BgpValueType> capabilityTlv = openmsg.getCapabilityTlv();
ListIterator<BgpValueType> listIterator = capabilityTlv.listIterator();
......@@ -798,7 +801,6 @@ class BgpChannelHandler extends IdleStateAwareChannelHandler {
boolean isFlowSpecVpnv4CapabilityCfg = false;
MultiProtocolExtnCapabilityTlv tempCapability;
boolean isMultiProtocolLsCapability = false;
boolean isMultiProtocolFlowSpecRpdCapability = false;
boolean isMultiProtocolFlowSpecCapability = false;
boolean isMultiProtocolVpnFlowSpecCapability = false;
BgpCfg.FlowSpec flowSpec = h.bgpconfig.flowSpecCapability();
......@@ -827,15 +829,16 @@ class BgpChannelHandler extends IdleStateAwareChannelHandler {
if (SAFI == tempCapability.getSafi()) {
isMultiProtocolLsCapability = true;
}
if (Constants.SAFI_FLOWSPEC_RPD_VALUE == tempCapability.getSafi()) {
isMultiProtocolFlowSpecRpdCapability = true;
}
}
if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) {
isFourOctetCapabilityExits = true;
capAsNum = ((FourOctetAsNumCapabilityTlv) tlv).getInt();
}
if (tlv.getType() == RpdCapabilityTlv.TYPE) {
isRpdCapabilityExits = true;
sendReceive = ((RpdCapabilityTlv) tlv).sendReceive();
}
}
if (isFourOctetCapabilityExits) {
......@@ -850,6 +853,12 @@ class BgpChannelHandler extends IdleStateAwareChannelHandler {
}
}
if (isRpdCapabilityExits) {
if (sendReceive > 2) {
throw new BgpParseException(BgpErrorType.OPEN_MESSAGE_ERROR, BgpErrorType.UNSUPPORTED_CAPABILITY, null);
}
}
if ((isLsCapabilityCfg)) {
if (!isMultiProtocolLsCapability) {
tempTlv = new MultiProtocolExtnCapabilityTlv(AFI, RES, SAFI);
......@@ -881,10 +890,8 @@ class BgpChannelHandler extends IdleStateAwareChannelHandler {
}
if ((isFlowSpecRpdCapabilityCfg)) {
if (!isMultiProtocolFlowSpecRpdCapability) {
tempTlv = new MultiProtocolExtnCapabilityTlv(Constants.AFI_FLOWSPEC_RPD_VALUE,
RES, Constants.SAFI_FLOWSPEC_RPD_VALUE,
Constants.RPD_CAPABILITY_SEND_VALUE);
if (!isRpdCapabilityExits) {
tempTlv = new RpdCapabilityTlv(Constants.RPD_CAPABILITY_SEND_VALUE);
unSupportedCapabilityTlv.add(tempTlv);
}
}
......