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.UnsignedInteger;
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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.AreaIdentifier;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.DomainIdentifier;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.IsisRouterIdentifier;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NlriType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.OspfInterfaceIdentifier;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.isis.lan.identifier.IsIsRouterIdentifier;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.isis.lan.identifier.IsIsRouterIdentifierBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.LocalNodeDescriptorsBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.RemoteNodeDescriptorsBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.node._case.NodeDescriptors;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.node._case.NodeDescriptorsBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.prefix._case.AdvertisingNodeDescriptorsBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.CRouterIdentifier;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.IsisNodeCase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.IsisNodeCaseBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.IsisPseudonodeCase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.IsisPseudonodeCaseBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.OspfNodeCase;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.OspfNodeCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.OspfPseudonodeCase;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.OspfPseudonodeCaseBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.isis.node._case.IsisNode;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.isis.node._case.IsisNodeBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.isis.pseudonode._case.IsisPseudonode;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.isis.pseudonode._case.IsisPseudonodeBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.ospf.node._case.OspfNode;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.ospf.node._case.OspfNodeBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.ospf.pseudonode._case.OspfPseudonode;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.node.identifier.c.router.identifier.ospf.pseudonode._case.OspfPseudonodeBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IsoSystemIdentifier;
50 import org.opendaylight.yangtools.yang.common.QName;
51 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
52 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
53 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
54 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
55 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
60 public final class NodeNlriParser {
62 private static final Logger LOG = LoggerFactory.getLogger(NodeNlriParser.class);
64 private NodeNlriParser() {
65 throw new UnsupportedOperationException();
68 private static final int OSPF_PSEUDONODE_ROUTER_ID_LENGTH = 8;
69 private static final int OSPF_ROUTER_ID_LENGTH = 4;
70 private static final int ISO_SYSTEM_ID_LENGTH = 6;
71 private static final int PSN_LENGTH = 1;
73 /* Node Descriptor TLVs */
74 private static final int AS_NUMBER = 512;
75 private static final int BGP_LS_ID = 513;
76 private static final int AREA_ID = 514;
77 private static final int IGP_ROUTER_ID = 515;
79 /* Node Descriptor QNames */
80 private static final NodeIdentifier AS_NUMBER_NID = new NodeIdentifier(QName.cachedReference(QName.create(NodeDescriptors.QNAME, "as-number")));
81 private static final NodeIdentifier AREA_NID = new NodeIdentifier(QName.cachedReference(QName.create(NodeDescriptors.QNAME, "area-id")));
82 private static final NodeIdentifier DOMAIN_NID = new NodeIdentifier(QName.cachedReference(QName.create(NodeDescriptors.QNAME, "domain-id")));
83 private static final NodeIdentifier ROUTER_NID = new NodeIdentifier(CRouterIdentifier.QNAME);
85 /* Router Identifier QNames */
86 private static final NodeIdentifier ISIS_NODE_NID = new NodeIdentifier(IsisNode.QNAME);
87 private static final NodeIdentifier ISIS_PSEUDONODE_NID = new NodeIdentifier(IsisPseudonode.QNAME);
88 private static final NodeIdentifier OSPF_NODE_NID = new NodeIdentifier(OspfNode.QNAME);
89 private static final NodeIdentifier OSPF_PSEUDONODE_NID = new NodeIdentifier(OspfPseudonode.QNAME);
90 private static final NodeIdentifier ISIS_ROUTER_NID = new NodeIdentifier(IsisRouterIdentifier.QNAME);
91 private static final NodeIdentifier ISO_SYSTEM_NID = new NodeIdentifier(QName.cachedReference(QName.create(NodeDescriptors.QNAME, "iso-system-id")));
92 private static final NodeIdentifier PSN_NID = new NodeIdentifier(QName.cachedReference(QName.create(NodeDescriptors.QNAME, "psn")));
93 private static final NodeIdentifier OSPF_ROUTER_NID = new NodeIdentifier(QName.cachedReference(QName.create(NodeDescriptors.QNAME, "ospf-router-id")));
94 private static final NodeIdentifier LAN_IFACE_NID = new NodeIdentifier(QName.cachedReference(QName.create(NodeDescriptors.QNAME, "lan-interface")));
96 static org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NodeIdentifier parseNodeDescriptors(final ByteBuf buffer, final NlriType nlriType, final boolean local) throws BGPParsingException {
97 AsNumber asnumber = null;
98 DomainIdentifier bgpId = null;
99 AreaIdentifier ai = null;
100 CRouterIdentifier routerId = null;
101 while (buffer.isReadable()) {
102 final int type = buffer.readUnsignedShort();
103 final int length = buffer.readUnsignedShort();
104 final ByteBuf value = buffer.readSlice(length);
105 if (LOG.isTraceEnabled()) {
106 LOG.trace("Parsing Node Descriptor: {}", ByteBufUtil.hexDump(value));
110 asnumber = new AsNumber(value.readUnsignedInt());
111 LOG.debug("Parsed {}", asnumber);
114 bgpId = new DomainIdentifier(value.readUnsignedInt());
115 LOG.debug("Parsed {}", bgpId);
118 ai = new AreaIdentifier(value.readUnsignedInt());
119 LOG.debug("Parsed area identifier {}", ai);
122 routerId = parseRouterId(value);
123 LOG.debug("Parsed Router Identifier {}", routerId);
126 throw new BGPParsingException("Node Descriptor not recognized, type: " + type);
129 LOG.trace("Finished parsing Node descriptors.");
133 return new LocalNodeDescriptorsBuilder().setAsNumber(asnumber).setAreaId(ai).setCRouterIdentifier(routerId).setDomainId(bgpId).build();
135 return new RemoteNodeDescriptorsBuilder().setAsNumber(asnumber).setAreaId(ai).setCRouterIdentifier(routerId).setDomainId(bgpId).build();
138 return new NodeDescriptorsBuilder().setAsNumber(asnumber).setAreaId(ai).setCRouterIdentifier(routerId).setDomainId(bgpId).build();
141 return new AdvertisingNodeDescriptorsBuilder().setAsNumber(asnumber).setAreaId(ai).setCRouterIdentifier(routerId).setDomainId(bgpId).build();
143 throw new IllegalStateException("NLRI type not recognized.");
147 private static CRouterIdentifier parseRouterId(final ByteBuf value) throws BGPParsingException {
148 if (value.readableBytes() == ISO_SYSTEM_ID_LENGTH || (value.readableBytes() == ISO_SYSTEM_ID_LENGTH + PSN_LENGTH && value.getByte(ISO_SYSTEM_ID_LENGTH) == 0)) {
149 return new IsisNodeCaseBuilder().setIsisNode(
150 new IsisNodeBuilder().setIsoSystemId(new IsoSystemIdentifier(ByteArray.readBytes(value, ISO_SYSTEM_ID_LENGTH))).build()).build();
152 if (value.readableBytes() == ISO_SYSTEM_ID_LENGTH + PSN_LENGTH) {
153 final IsIsRouterIdentifier iri = new IsIsRouterIdentifierBuilder().setIsoSystemId(
154 new IsoSystemIdentifier(ByteArray.readBytes(value, ISO_SYSTEM_ID_LENGTH))).build();
155 return new IsisPseudonodeCaseBuilder().setIsisPseudonode(new IsisPseudonodeBuilder().setIsIsRouterIdentifier(iri).setPsn((short) value.readByte()).build()).build();
157 if (value.readableBytes() == OSPF_ROUTER_ID_LENGTH) {
158 return new OspfNodeCaseBuilder().setOspfNode(
159 new OspfNodeBuilder().setOspfRouterId(value.readUnsignedInt()).build()).build();
161 if (value.readableBytes() == OSPF_PSEUDONODE_ROUTER_ID_LENGTH) {
162 return new OspfPseudonodeCaseBuilder().setOspfPseudonode(
163 new OspfPseudonodeBuilder().setOspfRouterId(value.readUnsignedInt()).setLanInterface(new OspfInterfaceIdentifier(value.readUnsignedInt())).build()).build();
165 throw new BGPParsingException("Router Id of invalid length " + value.readableBytes());
168 static void serializeNodeDescriptors(final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NodeIdentifier descriptors, final ByteBuf buffer) {
169 if (descriptors.getAsNumber() != null) {
170 TlvUtil.writeTLV(AS_NUMBER, Unpooled.copyInt(UnsignedInteger.valueOf(descriptors.getAsNumber().getValue()).intValue()), buffer);
172 if (descriptors.getDomainId() != null) {
173 TlvUtil.writeTLV(BGP_LS_ID, Unpooled.copyInt(UnsignedInteger.valueOf(descriptors.getDomainId().getValue()).intValue()), buffer);
175 if (descriptors.getAreaId() != null) {
176 TlvUtil.writeTLV(AREA_ID, Unpooled.copyInt(UnsignedInteger.valueOf(descriptors.getAreaId().getValue()).intValue()), buffer);
178 if (descriptors.getCRouterIdentifier() != null) {
179 final ByteBuf routerIdBuf = Unpooled.buffer();
180 serializeRouterId(descriptors.getCRouterIdentifier(), routerIdBuf);
181 TlvUtil.writeTLV(IGP_ROUTER_ID, routerIdBuf, buffer);
185 private static void serializeRouterId(final CRouterIdentifier routerId, final ByteBuf buffer) {
186 if (routerId instanceof IsisNodeCase) {
187 final IsisNode isis = ((IsisNodeCase) routerId).getIsisNode();
188 buffer.writeBytes(isis.getIsoSystemId().getValue());
189 } else if (routerId instanceof IsisPseudonodeCase) {
190 final IsisPseudonode isis = ((IsisPseudonodeCase) routerId).getIsisPseudonode();
191 buffer.writeBytes(isis.getIsIsRouterIdentifier().getIsoSystemId().getValue());
192 buffer.writeByte(((isis.getPsn() != null) ? isis.getPsn() : 0));
193 } else if (routerId instanceof OspfNodeCase) {
194 buffer.writeInt(UnsignedInteger.valueOf(((OspfNodeCase) routerId).getOspfNode().getOspfRouterId()).intValue());
195 } else if (routerId instanceof OspfPseudonodeCase) {
196 final OspfPseudonode node = ((OspfPseudonodeCase) routerId).getOspfPseudonode();
197 buffer.writeInt(UnsignedInteger.valueOf(node.getOspfRouterId()).intValue());
198 buffer.writeInt(UnsignedInteger.valueOf(node.getLanInterface().getValue()).intValue());
202 private static void serializeIsisNode(final ContainerNode isis, final ByteBuf buffer) {
203 buffer.writeBytes((byte[])isis.getChild(ISO_SYSTEM_NID).get().getValue());
206 private static void serializeOspfNode(final ContainerNode ospf, final ByteBuf buffer) {
207 buffer.writeInt(UnsignedInteger.valueOf((Long)ospf.getChild(OSPF_ROUTER_NID).get().getValue()).intValue());
210 private static void serializeRouterId(final ChoiceNode routerId, final ByteBuf buffer) {
211 if (routerId.getChild(ISIS_NODE_NID).isPresent()) {
212 serializeIsisNode((ContainerNode)routerId.getChild(ISIS_NODE_NID).get(), buffer);
213 } else if (routerId.getChild(ISIS_PSEUDONODE_NID).isPresent()) {
214 final ContainerNode isisPseudo = (ContainerNode)routerId.getChild(ISIS_PSEUDONODE_NID).get();
215 serializeIsisNode((ContainerNode) isisPseudo.getChild(ISIS_ROUTER_NID).get(), buffer);
216 if (isisPseudo.getChild(PSN_NID).isPresent()) {
217 buffer.writeByte(((Short)isisPseudo.getChild(PSN_NID).get().getValue()));
219 buffer.writeZero(PSN_LENGTH);
221 } else if (routerId.getChild(OSPF_NODE_NID).isPresent()) {
222 serializeOspfNode((ContainerNode)routerId.getChild(OSPF_NODE_NID).get(), buffer);
223 } else if (routerId.getChild(OSPF_PSEUDONODE_NID).isPresent()) {
224 final ContainerNode ospfPseudo = (ContainerNode)routerId.getChild(OSPF_PSEUDONODE_NID).get();
225 serializeOspfNode((ContainerNode)ospfPseudo.getChild(OSPF_NODE_NID), buffer);
226 buffer.writeInt(UnsignedInteger.valueOf((Long)ospfPseudo.getChild(LAN_IFACE_NID).get().getValue()).intValue());
230 static void serializeNodeDescriptors(final ContainerNode descriptors, final ByteBuf buffer) {
231 final Optional<DataContainerChild<? extends PathArgument, ?>> asNumber = descriptors.getChild(AS_NUMBER_NID);
232 if (asNumber.isPresent()) {
233 TlvUtil.writeTLV(AS_NUMBER, Unpooled.copyInt(UnsignedInteger.valueOf((Long)asNumber.get().getValue()).intValue()), buffer);
235 final Optional<DataContainerChild<? extends PathArgument, ?>> domainId = descriptors.getChild(DOMAIN_NID);
236 if (domainId.isPresent()) {
237 TlvUtil.writeTLV(BGP_LS_ID, Unpooled.copyInt(UnsignedInteger.valueOf((Long)domainId.get().getValue()).intValue()), buffer);
239 final Optional<DataContainerChild<? extends PathArgument, ?>> areaId = descriptors.getChild(AREA_NID);
240 if (areaId.isPresent()) {
241 TlvUtil.writeTLV(AREA_ID, Unpooled.copyInt(UnsignedInteger.valueOf((Long)domainId.get().getValue()).intValue()), buffer);
243 final Optional<DataContainerChild<? extends PathArgument, ?>> routerId = descriptors.getChild(ROUTER_NID);
244 if (routerId.isPresent()) {
245 final ByteBuf routerIdBuf = Unpooled.buffer();
246 serializeRouterId((ChoiceNode)routerId.get(), routerIdBuf);
247 TlvUtil.writeTLV(IGP_ROUTER_ID, routerIdBuf, buffer);