2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.protocol.bgp.parser.impl.message.update;
10 import static java.util.Objects.requireNonNull;
12 import io.netty.buffer.ByteBuf;
13 import io.netty.buffer.Unpooled;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
17 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
18 import org.opendaylight.protocol.bgp.parser.BGPError;
19 import org.opendaylight.protocol.bgp.parser.BGPTreatAsWithdrawException;
20 import org.opendaylight.protocol.bgp.parser.impl.message.update.AsPathSegmentParser.SegmentType;
21 import org.opendaylight.protocol.bgp.parser.spi.AbstractAttributeParser;
22 import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
23 import org.opendaylight.protocol.bgp.parser.spi.AttributeUtil;
24 import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
25 import org.opendaylight.protocol.bgp.parser.spi.RevisedErrorHandling;
26 import org.opendaylight.protocol.util.ReferenceCache;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.attributes.AsPath;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.attributes.AsPathBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.attributes.as.path.Segments;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.attributes.as.path.SegmentsBuilder;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * Parser for AS_PATH attribute.
40 public final class AsPathAttributeParser extends AbstractAttributeParser implements AttributeSerializer {
42 public static final int TYPE = 2;
44 private final ReferenceCache refCache;
45 private static final Logger LOG = LoggerFactory.getLogger(AsPathAttributeParser.class);
47 private static final AsPath EMPTY = new AsPathBuilder().setSegments(Collections.emptyList()).build();
49 public AsPathAttributeParser(final ReferenceCache refCache) {
50 this.refCache = requireNonNull(refCache);
54 public void parseAttribute(final ByteBuf buffer, final AttributesBuilder builder,
55 final RevisedErrorHandling errorHandling, final PeerSpecificParserConstraint constraint)
56 throws BGPDocumentedException, BGPTreatAsWithdrawException {
57 builder.setAsPath(parseAsPath(this.refCache, buffer, errorHandling));
61 public void serializeAttribute(final Attributes pathAttributes, final ByteBuf byteAggregator) {
62 final AsPath asPath = pathAttributes.getAsPath();
66 final ByteBuf segmentsBuffer = Unpooled.buffer();
67 if (asPath.getSegments() != null) {
68 for (final Segments segments : asPath.getSegments()) {
69 if (segments.getAsSequence() != null) {
70 AsPathSegmentParser.serializeAsList(segments.getAsSequence(), SegmentType.AS_SEQUENCE,
72 } else if (segments.getAsSet() != null) {
73 AsPathSegmentParser.serializeAsList(segments.getAsSet(), SegmentType.AS_SET, segmentsBuffer);
75 LOG.warn("Segment doesn't have AsSequence nor AsSet list.");
79 AttributeUtil.formatAttribute(AttributeUtil.TRANSITIVE, TYPE, segmentsBuffer, byteAggregator);
83 * Parses AS_PATH from bytes.
85 * @param refCache ReferenceCache shared reference of object
86 * @param buffer bytes to be parsed
87 * @return new ASPath object
88 * @throws BGPDocumentedException if there is no AS_SEQUENCE present (mandatory)
90 private static AsPath parseAsPath(final ReferenceCache refCache, final ByteBuf buffer,
91 final RevisedErrorHandling errorHandling) throws BGPDocumentedException, BGPTreatAsWithdrawException {
92 if (!buffer.isReadable()) {
96 final ArrayList<Segments> ases = new ArrayList<>();
97 boolean isSequence = false;
98 for (int readable = buffer.readableBytes(); readable != 0; readable = buffer.readableBytes()) {
100 throw errorHandling.reportError(BGPError.AS_PATH_MALFORMED,
101 "Insufficient AS PATH segment header length %s", readable);
104 final int type = buffer.readUnsignedByte();
105 final SegmentType segmentType = AsPathSegmentParser.parseType(type);
106 if (segmentType == null) {
107 throw errorHandling.reportError(BGPError.AS_PATH_MALFORMED, "Unknown AS PATH segment type %s", type);
109 final int count = buffer.readUnsignedByte();
110 if (count == 0 && errorHandling != RevisedErrorHandling.NONE) {
111 throw new BGPTreatAsWithdrawException(BGPError.AS_PATH_MALFORMED, "Empty AS_PATH segment");
114 // We read 2 bytes of header at this point
116 final int segmentLength = count * AsPathSegmentParser.AS_NUMBER_LENGTH;
117 if (segmentLength > readable) {
118 throw errorHandling.reportError(BGPError.AS_PATH_MALFORMED,
119 "Calculated segment length %s would overflow available buffer %s", segmentLength, readable);
122 final List<AsNumber> asList = AsPathSegmentParser.parseAsSegment(refCache, count,
123 buffer.readSlice(segmentLength));
124 if (segmentType == SegmentType.AS_SEQUENCE) {
125 ases.add(new SegmentsBuilder().setAsSequence(asList).build());
128 ases.add(new SegmentsBuilder().setAsSet(asList).build());
133 throw errorHandling.reportError(BGPError.AS_PATH_MALFORMED,
134 "AS_SEQUENCE must be present in AS_PATH attribute.");
138 return new AsPathBuilder().setSegments(ases).build();