YANG revision dates mass-update
[bgpcep.git] / bgp / parser-impl / src / main / java / org / opendaylight / protocol / bgp / parser / impl / message / update / CommunitiesAttributeParser.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.protocol.bgp.parser.impl.message.update;
9
10 import static java.util.Objects.requireNonNull;
11
12 import io.netty.buffer.ByteBuf;
13 import io.netty.buffer.Unpooled;
14 import java.util.ArrayList;
15 import java.util.Arrays;
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.spi.AbstractAttributeParser;
21 import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
22 import org.opendaylight.protocol.bgp.parser.spi.AttributeUtil;
23 import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
24 import org.opendaylight.protocol.bgp.parser.spi.RevisedErrorHandling;
25 import org.opendaylight.protocol.util.ByteArray;
26 import org.opendaylight.protocol.util.ReferenceCache;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.Attributes;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.Communities;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Community;
31
32 public final class CommunitiesAttributeParser extends AbstractAttributeParser implements AttributeSerializer {
33
34     public static final int TYPE = 8;
35
36     private static final int COMMUNITY_LENGTH = 4;
37
38     private static final byte[] NO_EXPORT = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x01 };
39
40     private static final byte[] NO_ADVERTISE = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x02 };
41
42     private static final byte[] NO_EXPORT_SUBCONFED = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x03 };
43
44     private static final byte[] LLGR_STALE = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0x00, (byte) 0x06 };
45
46     private static final byte[] NO_LLGR = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0x00, (byte) 0x07 };
47
48     private final ReferenceCache refCache;
49
50     public CommunitiesAttributeParser(final ReferenceCache refCache) {
51         this.refCache = requireNonNull(refCache);
52     }
53
54     @Override
55     public void parseAttribute(final ByteBuf buffer, final AttributesBuilder builder,
56             final RevisedErrorHandling errorHandling, final PeerSpecificParserConstraint constraint)
57                     throws BGPDocumentedException, BGPTreatAsWithdrawException {
58         final int readable = buffer.readableBytes();
59         if (readable == 0 && errorHandling != RevisedErrorHandling.NONE) {
60             throw new BGPTreatAsWithdrawException(BGPError.ATTR_LENGTH_ERROR, "Empty Community attribute");
61         }
62
63         if (readable % COMMUNITY_LENGTH != 0) {
64             throw errorHandling.reportError(BGPError.ATTR_LENGTH_ERROR,
65                 "Community attribute length must be a multiple of %s, have %s", COMMUNITY_LENGTH, readable);
66         }
67
68         final int count = readable / COMMUNITY_LENGTH;
69         final List<Communities> set = new ArrayList<>(count);
70         for (int i = 0; i < count; ++i) {
71             set.add((Communities) parseCommunity(this.refCache, buffer.readSlice(COMMUNITY_LENGTH)));
72         }
73         builder.setCommunities(set);
74     }
75
76    /**
77     * Parse known Community, if unknown, a new one will be created.
78     *
79     * @param refCache reference cache
80     * @param buffer byte array to be parsed
81     * @return new Community
82     */
83     private static Community parseCommunity(final ReferenceCache refCache, final ByteBuf buffer)
84             throws BGPDocumentedException {
85         if (buffer.readableBytes() != COMMUNITY_LENGTH) {
86             throw new BGPDocumentedException("Community with wrong length: "
87                     + buffer.readableBytes(), BGPError.OPT_ATTR_ERROR);
88         }
89         final byte[] body = ByteArray.getBytes(buffer, COMMUNITY_LENGTH);
90         if (Arrays.equals(body, NO_EXPORT)) {
91             return CommunityUtil.NO_EXPORT;
92         } else if (Arrays.equals(body, NO_ADVERTISE)) {
93             return CommunityUtil.NO_ADVERTISE;
94         } else if (Arrays.equals(body, NO_EXPORT_SUBCONFED)) {
95             return CommunityUtil.NO_EXPORT_SUBCONFED;
96         } else if (Arrays.equals(body, LLGR_STALE)) {
97             return CommunityUtil.LLGR_STALE;
98         } else if (Arrays.equals(body, NO_LLGR)) {
99             return CommunityUtil.NO_LLGR;
100         }
101         return CommunityUtil.create(refCache, buffer.readUnsignedShort(), buffer.readUnsignedShort());
102     }
103
104     @Override
105     public void serializeAttribute(final Attributes pathAttributes, final ByteBuf byteAggregator) {
106         final List<Communities> communities = pathAttributes.getCommunities();
107         if (communities == null || communities.isEmpty()) {
108             return;
109         }
110         final ByteBuf communitiesBuffer = Unpooled.buffer();
111         for (final Community community : communities) {
112             communitiesBuffer.writeShort(community.getAsNumber().getValue().shortValue());
113             communitiesBuffer.writeShort(community.getSemantics().shortValue());
114         }
115         AttributeUtil.formatAttribute(AttributeUtil.OPTIONAL | AttributeUtil.TRANSITIVE,
116                 TYPE, communitiesBuffer, byteAggregator);
117     }
118 }