use of org.opendaylight.protocol.bgp.parser.spi.RevisedErrorHandling in project bgpcep by opendaylight.
the class SimpleAttributeRegistry method parseAttributes.
@Override
public ParsedAttributes parseAttributes(final ByteBuf buffer, final PeerSpecificParserConstraint constraint) throws BGPDocumentedException, BGPParsingException {
final RevisedErrorHandling errorHandling = RevisedErrorHandling.from(constraint);
final Map<Integer, RawAttribute> attributes = new TreeMap<>();
BGPTreatAsWithdrawException withdrawCause = null;
while (buffer.isReadable()) {
try {
addAttribute(buffer, errorHandling, attributes);
} catch (BGPTreatAsWithdrawException e) {
LOG.info("Failed to completely parse attributes list.");
withdrawCause = e;
break;
}
}
/*
* TreeMap guarantees that we will be invoking the parser in the order
* of increasing attribute type.
*/
// We may have multiple attribute errors, each specifying a withdraw. We need to finish parsing the message
// all attributes before we can decide whether we can discard attributes, or whether we need to terminate
// the session.
final AttributesBuilder builder = new AttributesBuilder();
for (final Entry<Integer, RawAttribute> entry : attributes.entrySet()) {
LOG.debug("Parsing attribute type {}", entry.getKey());
final RawAttribute a = entry.getValue();
try {
a.parser.parseAttribute(a.buffer, builder, errorHandling, constraint);
} catch (BGPTreatAsWithdrawException e) {
LOG.info("Attribute {} indicated treat-as-withdraw", entry.getKey(), e);
if (withdrawCause == null) {
withdrawCause = e;
} else {
withdrawCause.addSuppressed(e);
}
}
}
builder.setUnrecognizedAttributes(BindingMap.ordered(this.unrecognizedAttributes));
return new ParsedAttributes(builder.build(), withdrawCause);
}
use of org.opendaylight.protocol.bgp.parser.spi.RevisedErrorHandling 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.spi.RevisedErrorHandling 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();
}
Aggregations