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