Merge "Split feature file"
[bgpcep.git] / bgp / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / nlri / PrefixNlriParser.java
1 /*
2  * Copyright (c) 2014 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.linkstate.nlri;
9
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.primitives.UnsignedBytes;
12 import io.netty.buffer.ByteBuf;
13 import io.netty.buffer.ByteBufUtil;
14 import io.netty.buffer.Unpooled;
15 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
16 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
17 import org.opendaylight.protocol.util.ByteArray;
18 import org.opendaylight.protocol.util.Ipv4Util;
19 import org.opendaylight.protocol.util.Ipv6Util;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.OspfRouteType;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.TopologyIdentifier;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.destination.c.linkstate.destination.PrefixDescriptors;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.destination.c.linkstate.destination.PrefixDescriptorsBuilder;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 @VisibleForTesting
29 public final class PrefixNlriParser {
30
31     private static final Logger LOG = LoggerFactory.getLogger(PrefixNlriParser.class);
32
33     private PrefixNlriParser() {
34         throw new UnsupportedOperationException();
35     }
36
37     /* Prefix Descriptor TLVs */
38     private static final int OSPF_ROUTE_TYPE = 264;
39     private static final int IP_REACHABILITY = 265;
40
41     static PrefixDescriptors parsePrefixDescriptors(final ByteBuf buffer, final boolean ipv4) throws BGPParsingException {
42         final PrefixDescriptorsBuilder builder = new PrefixDescriptorsBuilder();
43         while (buffer.isReadable()) {
44             final int type = buffer.readUnsignedShort();
45             final int length = buffer.readUnsignedShort();
46             final ByteBuf value = buffer.readSlice(length);
47             if (LOG.isTraceEnabled()) {
48                 LOG.trace("Parsing Prefix Descriptor: {}", ByteBufUtil.hexDump(value));
49             }
50             switch (type) {
51             case TlvUtil.MULTI_TOPOLOGY_ID:
52                 final TopologyIdentifier topologyId = new TopologyIdentifier(value.readShort() & TlvUtil.TOPOLOGY_ID_OFFSET);
53                 builder.setMultiTopologyId(topologyId);
54                 LOG.trace("Parsed Topology Identifier: {}", topologyId);
55                 break;
56             case OSPF_ROUTE_TYPE:
57                 final int rt = value.readByte();
58                 final OspfRouteType routeType = OspfRouteType.forValue(rt);
59                 if (routeType == null) {
60                     throw new BGPParsingException("Unknown OSPF Route Type: " + rt);
61                 }
62                 builder.setOspfRouteType(routeType);
63                 LOG.trace("Parser RouteType: {}", routeType);
64                 break;
65             case IP_REACHABILITY:
66                 IpPrefix prefix = null;
67                 final int prefixLength = value.readByte();
68                 final int size = prefixLength / Byte.SIZE + ((prefixLength % Byte.SIZE == 0) ? 0 : 1);
69                 if (size != value.readableBytes()) {
70                     LOG.debug("Expected length {}, actual length {}.", size, value.readableBytes());
71                     throw new BGPParsingException("Illegal length of IP reachability TLV: " + (value.readableBytes()));
72                 }
73                 prefix = (ipv4) ? new IpPrefix(Ipv4Util.prefixForBytes(ByteArray.readBytes(value, size), prefixLength)):
74                     new IpPrefix(Ipv6Util.prefixForBytes(ByteArray.readBytes(value, size), prefixLength));
75                 builder.setIpReachabilityInformation(prefix);
76                 LOG.trace("Parsed IP reachability info: {}", prefix);
77                 break;
78             default:
79                 throw new BGPParsingException("Prefix Descriptor not recognized, type: " + type);
80             }
81         }
82         LOG.debug("Finished parsing Prefix descriptors.");
83         return builder.build();
84     }
85
86     static void serializePrefixDescriptors(final PrefixDescriptors descriptors, final ByteBuf buffer) {
87         if (descriptors.getMultiTopologyId() != null) {
88             TlvUtil.writeTLV(TlvUtil.MULTI_TOPOLOGY_ID, Unpooled.copyShort(descriptors.getMultiTopologyId().getValue()), buffer);
89         }
90         if (descriptors.getOspfRouteType() != null) {
91             TlvUtil.writeTLV(OSPF_ROUTE_TYPE,
92                 Unpooled.wrappedBuffer(new byte[] {UnsignedBytes.checkedCast(descriptors.getOspfRouteType().getIntValue()) }), buffer);
93         }
94         if (descriptors.getIpReachabilityInformation() != null) {
95             final IpPrefix prefix = descriptors.getIpReachabilityInformation();
96             byte[] prefixBytes = null;
97             if (prefix.getIpv4Prefix() != null) {
98                 prefixBytes = Ipv4Util.bytesForPrefixBegin(prefix.getIpv4Prefix());
99             } else if (prefix.getIpv6Prefix() != null) {
100                 prefixBytes = Ipv6Util.bytesForPrefixBegin(prefix.getIpv6Prefix());
101             }
102             TlvUtil.writeTLV(IP_REACHABILITY, Unpooled.wrappedBuffer(prefixBytes), buffer);
103         }
104     }
105 }