use of org.opendaylight.protocol.bgp.parser.BGPTreatAsWithdrawException in project bgpcep by opendaylight.
the class BGPUpdateMessageParser method parseMessageBody.
/**
* Parse Update message from buffer. Calls {@link #checkMandatoryAttributesPresence(Update, RevisedErrorHandling)}
* to check for presence of mandatory attributes.
*
* @param buffer Encoded BGP message in ByteBuf
* @param messageLength Length of the BGP message
* @param constraint Peer specific constraints
* @return Parsed Update message body
*/
@Override
public Update parseMessageBody(final ByteBuf buffer, final int messageLength, final PeerSpecificParserConstraint constraint) throws BGPDocumentedException {
checkArgument(buffer != null && buffer.isReadable(), "Buffer cannot be null or empty.");
final UpdateBuilder builder = new UpdateBuilder();
final boolean isMultiPathSupported = MultiPathSupportUtil.isTableTypeSupported(constraint, new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class));
final RevisedErrorHandling errorHandling = RevisedErrorHandling.from(constraint);
final int withdrawnRoutesLength = buffer.readUnsignedShort();
if (withdrawnRoutesLength > 0) {
final List<WithdrawnRoutes> withdrawnRoutes = new ArrayList<>();
final ByteBuf withdrawnRoutesBuffer = buffer.readSlice(withdrawnRoutesLength);
while (withdrawnRoutesBuffer.isReadable()) {
final WithdrawnRoutesBuilder withdrawnRoutesBuilder = new WithdrawnRoutesBuilder();
if (isMultiPathSupported) {
withdrawnRoutesBuilder.setPathId(PathIdUtil.readPathId(withdrawnRoutesBuffer));
}
withdrawnRoutesBuilder.setPrefix(readPrefix(withdrawnRoutesBuffer, errorHandling, "Withdrawn Routes"));
withdrawnRoutes.add(withdrawnRoutesBuilder.build());
}
builder.setWithdrawnRoutes(withdrawnRoutes);
}
final int totalPathAttrLength = buffer.readUnsignedShort();
if (withdrawnRoutesLength == 0 && totalPathAttrLength == 0) {
return builder.build();
}
Optional<BGPTreatAsWithdrawException> withdrawCauseOpt;
if (totalPathAttrLength > 0) {
final ParsedAttributes attributes = parseAttributes(buffer, totalPathAttrLength, constraint);
builder.setAttributes(attributes.getAttributes());
withdrawCauseOpt = attributes.getWithdrawCause();
} else {
withdrawCauseOpt = Optional.empty();
}
final List<Nlri> nlri = new ArrayList<>();
while (buffer.isReadable()) {
final NlriBuilder nlriBuilder = new NlriBuilder();
if (isMultiPathSupported) {
nlriBuilder.setPathId(PathIdUtil.readPathId(buffer));
}
nlriBuilder.setPrefix(readPrefix(buffer, errorHandling, "NLRI"));
nlri.add(nlriBuilder.build());
}
if (!nlri.isEmpty()) {
builder.setNlri(nlri);
}
try {
checkMandatoryAttributesPresence(builder.build(), errorHandling);
} catch (BGPTreatAsWithdrawException e) {
LOG.debug("Well-known mandatory attributes missing", e);
if (withdrawCauseOpt.isPresent()) {
final BGPTreatAsWithdrawException exception = withdrawCauseOpt.get();
exception.addSuppressed(e);
withdrawCauseOpt = Optional.of(exception);
} else {
withdrawCauseOpt = Optional.of(e);
}
}
Update msg = builder.build();
if (withdrawCauseOpt.isPresent()) {
// Attempt to apply treat-as-withdraw
msg = withdrawUpdate(msg, errorHandling, withdrawCauseOpt.get());
}
LOG.debug("BGP Update message was parsed {}.", msg);
return msg;
}
use of org.opendaylight.protocol.bgp.parser.BGPTreatAsWithdrawException in project bgpcep by opendaylight.
the class BGPUpdateMessageParser method withdrawUpdate.
private Update withdrawUpdate(final Update parsed, final RevisedErrorHandling errorHandling, final BGPTreatAsWithdrawException withdrawCause) throws BGPDocumentedException {
if (errorHandling == RevisedErrorHandling.NONE) {
throw new BGPDocumentedException(withdrawCause);
}
// TODO: additional checks as per RFC7606 section 5.2
LOG.debug("Converting BGP Update message {} to withdraw", parsed, withdrawCause);
final UpdateBuilder builder = new UpdateBuilder();
final List<Nlri> nlris = parsed.getNlri();
final List<WithdrawnRoutes> withdrawn;
if (nlris != null && !nlris.isEmpty()) {
withdrawn = Streams.concat(parsed.nonnullWithdrawnRoutes().stream(), nlris.stream().map(nlri -> new WithdrawnRoutesBuilder(nlri).build())).collect(ImmutableList.toImmutableList());
} else {
withdrawn = parsed.getWithdrawnRoutes();
}
builder.setWithdrawnRoutes(withdrawn);
final Attributes attributes = parsed.getAttributes();
if (attributes != null) {
builder.setAttributes(withdrawAttributes(attributes, withdrawCause));
}
return builder.build();
}
use of org.opendaylight.protocol.bgp.parser.BGPTreatAsWithdrawException in project bgpcep by opendaylight.
the class ClusterIdAttributeParser method parseAttribute.
@Override
public void parseAttribute(final ByteBuf buffer, final AttributesBuilder builder, final RevisedErrorHandling errorHandling, final PeerSpecificParserConstraint constraint) throws BGPDocumentedException, BGPTreatAsWithdrawException {
if (errorHandling == RevisedErrorHandling.EXTERNAL) {
// RFC7606 section 7.10
LOG.debug("Discarded CLUSTER_LIST attribute from external peer");
return;
}
final int readable = buffer.readableBytes();
if (readable == 0 && errorHandling != RevisedErrorHandling.NONE) {
throw new BGPTreatAsWithdrawException(BGPError.ATTR_LENGTH_ERROR, "Empty CLUSTER_LIST attribute");
}
if (readable % Ipv4Util.IP4_LENGTH != 0) {
throw errorHandling.reportError(BGPError.ATTR_LENGTH_ERROR, "Length of CLUSTER_LIST should be a multiple of 4, but is %s", readable);
}
final int count = readable / Ipv4Util.IP4_LENGTH;
final List<ClusterIdentifier> list = new ArrayList<>(count);
for (int i = 0; i < count; ++i) {
list.add(new ClusterIdentifier(Ipv4Util.addressForByteBuf(buffer)));
}
builder.setClusterId(new ClusterIdBuilder().setCluster(list).build());
}
Aggregations