this.handler.serializeAttribute(expected, actual);
assertArrayEquals(PE_DISTINGUISHER_LABELS, ByteArray.readAllBytes(actual));
final Attributes actualAttr = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(PE_DISTINGUISHER_LABELS), null);
+ Unpooled.wrappedBuffer(PE_DISTINGUISHER_LABELS), null).getAttributes();
assertEquals(expected, actualAttr);
}
assertArrayEquals(BIDIR_PIM_EXPECTED, ByteArray.readAllBytes(actual));
final Attributes expected = buildBidirPimTreeAttribute();
final Attributes actualAttr = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(BIDIR_PIM_EXPECTED), null);
+ Unpooled.wrappedBuffer(BIDIR_PIM_EXPECTED), null).getAttributes();
assertEquals(expected, actualAttr);
}
assertArrayEquals(PIM_SM_TREE_EXPECTED, ByteArray.readAllBytes(actual));
final Attributes expected = buildPimSMTreeAttribute();
final Attributes actualAttr = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(PIM_SM_TREE_EXPECTED), null);
+ Unpooled.wrappedBuffer(PIM_SM_TREE_EXPECTED), null).getAttributes();
assertEquals(expected, actualAttr);
}
public void parsePimSSMTree() throws Exception {
final Attributes expected = buildPimSSMTreeAttribute();
final Attributes actual = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(PIM_SSM_TREE_EXPECTED), null);
+ Unpooled.wrappedBuffer(PIM_SSM_TREE_EXPECTED), null).getAttributes();
assertEquals(expected, actual);
}
assertArrayEquals(M_LDP_P2MP_LSP_EXPECTED_IPV4, ByteArray.readAllBytes(actualIpv4));
final Attributes actualIpv4Attribute = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(M_LDP_P2MP_LSP_EXPECTED_IPV4_2), null);
+ Unpooled.wrappedBuffer(M_LDP_P2MP_LSP_EXPECTED_IPV4_2), null).getAttributes();
assertEquals(expectedIpv4Att, actualIpv4Attribute);
final Attributes expectedIpv6Att = buildMldpP2mpLspIpv6Attribute();
assertArrayEquals(M_LDP_P2MP_LSP_EXPECTED_IPV6, ByteArray.readAllBytes(actualIpv6));
final Attributes actualIpv6Attribute = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(M_LDP_P2MP_LSP_EXPECTED_IPV6), null);
+ Unpooled.wrappedBuffer(M_LDP_P2MP_LSP_EXPECTED_IPV6), null).getAttributes();
assertEquals(expectedIpv6Att, actualIpv6Attribute);
final ByteBuf actualL2vpn = Unpooled.buffer();
final Attributes actualWrongFamily = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(M_LDP_P2MP_LSP_EXPECTED_WRONG_FAMILY), null);
+ Unpooled.wrappedBuffer(M_LDP_P2MP_LSP_EXPECTED_WRONG_FAMILY), null).getAttributes();
assertEquals(buildWOTunnelInfAttribute(), actualWrongFamily);
final Attributes expectedL2vpnAtt = buildMldpp2MPLspL2vpnAttribute();
final Attributes actualL2vpnAttribute = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(M_LDP_P2MP_LSP_EXPECTED_L2VPN), null);
+ Unpooled.wrappedBuffer(M_LDP_P2MP_LSP_EXPECTED_L2VPN), null).getAttributes();
assertEquals(expectedL2vpnAtt, actualL2vpnAttribute);
final ByteBuf actualL2vp = Unpooled.buffer();
this.handler.serializeAttribute(expected, actual);
assertArrayEquals(RSVP_TE_P2MP_LSP_LSP_EXPECTED, ByteArray.readAllBytes(actual));
final Attributes actualAttr = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(RSVP_TE_P2MP_LSP_LSP_EXPECTED), null);
+ Unpooled.wrappedBuffer(RSVP_TE_P2MP_LSP_LSP_EXPECTED), null).getAttributes();
assertEquals(expected, actualAttr);
}
this.handler.serializeAttribute(expected, actual);
assertArrayEquals(INGRESS_REPLICATION_EXPECTED, ByteArray.readAllBytes(actual));
final Attributes actualAttr = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(INGRESS_REPLICATION_EXPECTED), null);
+ Unpooled.wrappedBuffer(INGRESS_REPLICATION_EXPECTED), null).getAttributes();
assertEquals(expected, actualAttr);
}
assertArrayEquals(M_LDP_MP_2_MP_LSP_EXPECTED, ByteArray.readAllBytes(actual));
final Attributes actualAttr = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(M_LDP_MP_2_MP_LSP_EXPECTED), null);
+ Unpooled.wrappedBuffer(M_LDP_MP_2_MP_LSP_EXPECTED), null).getAttributes();
assertEquals(expected, actualAttr);
final Attributes actualWrong = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(M_LDP_MP_2_MP_LSP_WRONG), null);
+ Unpooled.wrappedBuffer(M_LDP_MP_2_MP_LSP_WRONG), null).getAttributes();
assertEquals(buildWOTunnelInfAttribute(), actualWrong);
final Attributes wrongAttribute = buildMldpMP2mpLspWrongAttribute();
assertArrayEquals(NO_TUNNEL_INFORMATION_PRESENT_EXPECTED, ByteArray.readAllBytes(actual));
final Attributes expected = buildWOTunnelInfAttribute();
final Attributes actualAttr = this.handler.parseAttributes(
- Unpooled.wrappedBuffer(NO_TUNNEL_INFORMATION_PRESENT_EXPECTED), null);
+ Unpooled.wrappedBuffer(NO_TUNNEL_INFORMATION_PRESENT_EXPECTED), null).getAttributes();
assertEquals(expected, actualAttr);
}
import io.netty.buffer.Unpooled;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
import org.opendaylight.protocol.bgp.parser.BGPError;
import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.BGPTreatAsWithdrawException;
import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
import org.opendaylight.protocol.bgp.parser.impl.message.update.AsPathAttributeParser;
import org.opendaylight.protocol.bgp.parser.impl.message.update.NextHopAttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.MessageSerializer;
import org.opendaylight.protocol.bgp.parser.spi.MessageUtil;
import org.opendaylight.protocol.bgp.parser.spi.MultiPathSupportUtil;
+import org.opendaylight.protocol.bgp.parser.spi.ParsedAttributes;
import org.opendaylight.protocol.bgp.parser.spi.PathIdUtil;
import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
import org.opendaylight.protocol.util.ByteBufWriteUtil;
MessageUtil.formatMessage(TYPE, messageBody, bytes);
}
- private void writePathIdPrefix(final ByteBuf byteBuf, final PathId pathId, final Ipv4Prefix ipv4Prefix) {
+ private static void writePathIdPrefix(final ByteBuf byteBuf, final PathId pathId, final Ipv4Prefix ipv4Prefix) {
PathIdUtil.writePathId(pathId, byteBuf);
ByteBufWriteUtil.writeMinimalPrefix(ipv4Prefix, byteBuf);
}
if (withdrawnRoutesLength == 0 && totalPathAttrLength == 0) {
return builder.build();
}
+ final Optional<BGPTreatAsWithdrawException> withdrawCause;
if (totalPathAttrLength > 0) {
+ final ParsedAttributes attributes;
try {
- final Attributes attributes
- = this.reg.parseAttributes(buffer.readSlice(totalPathAttrLength), constraint);
- builder.setAttributes(attributes);
+ attributes = this.reg.parseAttributes(buffer.readSlice(totalPathAttrLength), constraint);
} catch (final RuntimeException | BGPParsingException e) {
// Catch everything else and turn it into a BGPDocumentedException
throw new BGPDocumentedException("Could not parse BGP attributes.", BGPError.MALFORMED_ATTR_LIST, e);
}
+ builder.setAttributes(attributes.getAttributes());
+ withdrawCause = attributes.getWithdrawCause();
+ } else {
+ withdrawCause = Optional.empty();
}
final List<Nlri> nlri = new ArrayList<>();
while (buffer.isReadable()) {
if (!nlri.isEmpty()) {
builder.setNlri(nlri);
}
- final Update msg = builder.build();
+ Update msg = builder.build();
checkMandatoryAttributesPresence(msg);
+
+ if (withdrawCause.isPresent()) {
+ // FIXME: BGPCEP-359: check if we can treat the message as withdraw and convert the message
+ throw withdrawCause.get().toDocumentedException();
+ }
+
LOG.debug("BGP Update message was parsed {}.", msg);
return msg;
}
final BGPExtensionProviderContext providerContext = ServiceLoaderBGPExtensionProviderContext
.getSingletonInstance();
final Attributes pathAttributes = providerContext.getAttributeRegistry()
- .parseAttributes(buffer, null);
+ .parseAttributes(buffer, null).getAttributes();
final Aigp aigp = pathAttributes.getAigp();
final AigpTlv tlv = aigp.getAigpTlv();
final BGPExtensionProviderContext providerContext = ServiceLoaderBGPExtensionProviderContext
.getSingletonInstance();
final Attributes pathAttributes = providerContext.getAttributeRegistry()
- .parseAttributes(inputData, null);
+ .parseAttributes(inputData, null).getAttributes();
final Aigp aigp = pathAttributes.getAigp();
final AttributesBuilder pathAttributesBuilder = new AttributesBuilder();
.serializeAttribute(paBuilder.build(), actual);
assertArrayEquals(CommunitiesBytes, ByteArray.getAllBytes(actual));
final Attributes attributeOut = ServiceLoaderBGPExtensionProviderContext.getSingletonInstance()
- .getAttributeRegistry().parseAttributes(actual, null);
+ .getAttributeRegistry().parseAttributes(actual, null).getAttributes();
assertEquals(comms, attributeOut.getCommunities());
}
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
+import org.opendaylight.protocol.bgp.parser.BGPError;
import org.opendaylight.protocol.bgp.parser.BGPParsingException;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
* @param buffer Input buffer.
* @param constraints Peer specific constraint.
* @return Decoded BGP Attribute.
- * @throws BGPDocumentedException
- * @throws BGPParsingException
+ * @throws BGPDocumentedException when an unrecoverable error occurs, which is documented via {@link BGPError}
+ * @throws BGPParsingException when a general unrecoverable parsing error occurs
*/
- @Nonnull Attributes parseAttributes(@Nonnull ByteBuf buffer, @Nullable PeerSpecificParserConstraint constraints)
- throws BGPDocumentedException, BGPParsingException;
+ @Nonnull ParsedAttributes parseAttributes(@Nonnull ByteBuf buffer,
+ @Nullable PeerSpecificParserConstraint constraints) throws BGPDocumentedException, BGPParsingException;
/**
* Serialize BGP Attribute to buffer.
--- /dev/null
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.parser.spi;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.protocol.bgp.parser.BGPTreatAsWithdrawException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
+
+/**
+ * Parsed {@link Attributes}, potentially indicating withdraw.
+ *
+ * @author Robert Varga
+ */
+public final class ParsedAttributes {
+ private final @NonNull Attributes attributes;
+ private final @Nullable BGPTreatAsWithdrawException withdrawCause;
+
+ public ParsedAttributes(final @NonNull Attributes attributes,
+ final @Nullable BGPTreatAsWithdrawException withdrawCause) {
+ this.attributes = requireNonNull(attributes);
+ this.withdrawCause = withdrawCause;
+ }
+
+ public @NonNull Attributes getAttributes() {
+ return attributes;
+ }
+
+ public @NonNull Optional<BGPTreatAsWithdrawException> getWithdrawCause() {
+ return Optional.ofNullable(withdrawCause);
+ }
+}
import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry;
import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
+import org.opendaylight.protocol.bgp.parser.spi.ParsedAttributes;
import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
import org.opendaylight.protocol.bgp.parser.spi.RevisedErrorHandling;
import org.opendaylight.protocol.concepts.AbstractRegistration;
}
@Override
- public Attributes parseAttributes(final ByteBuf buffer, final PeerSpecificParserConstraint constraint)
+ 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<>();
while (buffer.isReadable()) {
addAttribute(buffer, errorHandling, attributes);
}
+
/*
* TreeMap guarantees that we will be invoking the parser in the order
* of increasing attribute type.
}
}
builder.setUnrecognizedAttributes(this.unrecognizedAttributes);
-
- // FIXME: BGPCEP-359 report withdrawCause upstream, so it can be handled properly
- if (withdrawCause != null) {
- throw withdrawCause.toDocumentedException();
- }
-
- return builder.build();
+ return new ParsedAttributes(builder.build(), withdrawCause);
}
@Override
public void testUnrecognizedAttributes() throws BGPDocumentedException, BGPParsingException {
final byte[] attributeBytes = { (byte)0xe0, 0x00, 0x05, 0x01, 0x02, 0x03, 0x04, 0x05 };
final List<UnrecognizedAttributes> unrecogAttribs = simpleAttrReg
- .parseAttributes(Unpooled.wrappedBuffer(attributeBytes), null).getUnrecognizedAttributes();
+ .parseAttributes(Unpooled.wrappedBuffer(attributeBytes), null).getAttributes().getUnrecognizedAttributes();
assertEquals(UNRECOGNIZED_ATTRIBUTE_COUNT, unrecogAttribs.size());
final UnrecognizedAttributes unrecogAttrib = unrecogAttribs.get(FIRST_ATTRIBUTE);
final UnrecognizedAttributesKey expectedAttribKey =