2 * Copyright (c) 2014 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.linkstate.nlri;
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.base.Optional;
12 import com.google.common.primitives.UnsignedBytes;
13 import io.netty.buffer.ByteBuf;
14 import io.netty.buffer.ByteBufUtil;
15 import io.netty.buffer.Unpooled;
16 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
17 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
18 import org.opendaylight.protocol.util.ByteArray;
19 import org.opendaylight.protocol.util.Ipv4Util;
20 import org.opendaylight.protocol.util.Ipv6Util;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NlriType;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.OspfRouteType;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.TopologyIdentifier;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.prefix._case.PrefixDescriptors;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.prefix._case.PrefixDescriptorsBuilder;
29 import org.opendaylight.yangtools.yang.common.QName;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
32 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
33 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 public final class PrefixNlriParser {
40 private static final Logger LOG = LoggerFactory.getLogger(PrefixNlriParser.class);
42 private PrefixNlriParser() {
43 throw new UnsupportedOperationException();
46 /* Prefix Descriptor TLVs */
47 private static final int OSPF_ROUTE_TYPE = 264;
48 private static final int IP_REACHABILITY = 265;
50 /* Prefix Descriptor QNames */
51 private static final NodeIdentifier OSPF_ROUTE_NID = new NodeIdentifier(QName.cachedReference(QName.create(PrefixDescriptors.QNAME, "ospf-route-type")));
52 private static final NodeIdentifier IP_REACH_NID = new NodeIdentifier(QName.cachedReference(QName.create(PrefixDescriptors.QNAME, "ip-reachability-information")));
54 static PrefixDescriptors parsePrefixDescriptors(final ByteBuf buffer, final boolean ipv4) throws BGPParsingException {
55 final PrefixDescriptorsBuilder builder = new PrefixDescriptorsBuilder();
56 while (buffer.isReadable()) {
57 final int type = buffer.readUnsignedShort();
58 final int length = buffer.readUnsignedShort();
59 final ByteBuf value = buffer.readSlice(length);
60 if (LOG.isTraceEnabled()) {
61 LOG.trace("Parsing Prefix Descriptor: {}", ByteBufUtil.hexDump(value));
64 case TlvUtil.MULTI_TOPOLOGY_ID:
65 final TopologyIdentifier topologyId = new TopologyIdentifier(value.readShort() & TlvUtil.TOPOLOGY_ID_OFFSET);
66 builder.setMultiTopologyId(topologyId);
67 LOG.trace("Parsed Topology Identifier: {}", topologyId);
70 final int rt = value.readByte();
71 final OspfRouteType routeType = OspfRouteType.forValue(rt);
72 if (routeType == null) {
73 throw new BGPParsingException("Unknown OSPF Route Type: " + rt);
75 builder.setOspfRouteType(routeType);
76 LOG.trace("Parser RouteType: {}", routeType);
79 IpPrefix prefix = null;
80 final int prefixLength = value.readByte();
81 final int size = prefixLength / Byte.SIZE + ((prefixLength % Byte.SIZE == 0) ? 0 : 1);
82 if (size != value.readableBytes()) {
83 LOG.debug("Expected length {}, actual length {}.", size, value.readableBytes());
84 throw new BGPParsingException("Illegal length of IP reachability TLV: " + (value.readableBytes()));
86 prefix = (ipv4) ? new IpPrefix(Ipv4Util.prefixForBytes(ByteArray.readBytes(value, size), prefixLength)):
87 new IpPrefix(Ipv6Util.prefixForBytes(ByteArray.readBytes(value, size), prefixLength));
88 builder.setIpReachabilityInformation(prefix);
89 LOG.trace("Parsed IP reachability info: {}", prefix);
92 throw new BGPParsingException("Prefix Descriptor not recognized, type: " + type);
95 LOG.debug("Finished parsing Prefix descriptors.");
96 return builder.build();
99 static void serializePrefixDescriptors(final PrefixDescriptors descriptors, final ByteBuf buffer) {
100 if (descriptors.getMultiTopologyId() != null) {
101 TlvUtil.writeTLV(TlvUtil.MULTI_TOPOLOGY_ID, Unpooled.copyShort(descriptors.getMultiTopologyId().getValue()), buffer);
103 if (descriptors.getOspfRouteType() != null) {
104 TlvUtil.writeTLV(OSPF_ROUTE_TYPE,
105 Unpooled.wrappedBuffer(new byte[] {UnsignedBytes.checkedCast(descriptors.getOspfRouteType().getIntValue()) }), buffer);
107 if (descriptors.getIpReachabilityInformation() != null) {
108 final IpPrefix prefix = descriptors.getIpReachabilityInformation();
109 byte[] prefixBytes = null;
110 if (prefix.getIpv4Prefix() != null) {
111 prefixBytes = Ipv4Util.bytesForPrefixBegin(prefix.getIpv4Prefix());
112 } else if (prefix.getIpv6Prefix() != null) {
113 prefixBytes = Ipv6Util.bytesForPrefixBegin(prefix.getIpv6Prefix());
115 TlvUtil.writeTLV(IP_REACHABILITY, Unpooled.wrappedBuffer(prefixBytes), buffer);
119 private static int domOspfRouteTypeValue(final String ospfRouteType) {
120 switch(ospfRouteType) {
138 static NlriType serializePrefixDescriptors(final ContainerNode descriptors, final ByteBuf buffer) {
139 if (descriptors.getChild(TlvUtil.MULTI_TOPOLOGY_NID).isPresent()) {
140 TlvUtil.writeTLV(TlvUtil.MULTI_TOPOLOGY_ID, Unpooled.copyShort((Short)descriptors.getChild(TlvUtil.MULTI_TOPOLOGY_NID).get().getValue()), buffer);
142 final Optional<DataContainerChild<? extends PathArgument, ?>> ospfRoute = descriptors.getChild(OSPF_ROUTE_NID);
143 if (ospfRoute.isPresent()) {
144 // DOM representation contains values as are in the model, not as are in generated enum
145 TlvUtil.writeTLV(OSPF_ROUTE_TYPE,
146 Unpooled.wrappedBuffer(new byte[] {UnsignedBytes.checkedCast(domOspfRouteTypeValue((String)ospfRoute.get().getValue())) }), buffer);
148 byte[] prefixBytes = null;
149 NlriType prefixType = null;
150 if (descriptors.getChild(IP_REACH_NID).isPresent()) {
151 final String prefix = (String)descriptors.getChild(IP_REACH_NID).get().getValue();
152 // DOM data does not have any information what kind of prefix is it holding,
153 // therefore we need to rely on the pattern matcher in Ipv4Prefix constructor
155 prefixBytes = Ipv4Util.bytesForPrefixBegin(new Ipv4Prefix(prefix));
156 prefixType = NlriType.Ipv4Prefix;
157 } catch(final IllegalArgumentException e) {
158 prefixBytes = Ipv6Util.bytesForPrefixBegin(new Ipv6Prefix(prefix));
159 prefixType = NlriType.Ipv6Prefix;
161 TlvUtil.writeTLV(IP_REACHABILITY, Unpooled.wrappedBuffer(prefixBytes), buffer);