BUG-4692: Migrate TCP-MD5 support in bgp package to netty's native-epoll
[bgpcep.git] / bgp / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / nlri / LinkNlriParser.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 io.netty.buffer.ByteBuf;
12 import io.netty.buffer.ByteBufUtil;
13 import io.netty.buffer.Unpooled;
14 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
15 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
16 import org.opendaylight.protocol.util.Ipv4Util;
17 import org.opendaylight.protocol.util.Ipv6Util;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.Ipv4InterfaceIdentifier;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.Ipv6InterfaceIdentifier;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NlriType;
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.ObjectType;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.destination.CLinkstateDestination;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.LinkCase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.LinkCaseBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.LinkDescriptors;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.LinkDescriptorsBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.LocalNodeDescriptors;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.RemoteNodeDescriptors;
30 import org.opendaylight.yangtools.yang.common.QName;
31 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
32 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 @VisibleForTesting
37 public final class LinkNlriParser implements NlriTypeCaseParser, NlriTypeCaseSerializer {
38
39     private static final Logger LOG = LoggerFactory.getLogger(LinkNlriParser.class);
40
41     /* Link Descriptor TLVs */
42     private static final int LINK_LR_IDENTIFIERS = 258;
43     private static final int IPV4_IFACE_ADDRESS = 259;
44     private static final int IPV4_NEIGHBOR_ADDRESS = 260;
45     private static final int IPV6_IFACE_ADDRESS = 261;
46     private static final int IPV6_NEIGHBOR_ADDRESS = 262;
47
48     /* Node Descriptor Type */
49     private static final int LOCAL_NODE_DESCRIPTORS_TYPE = 256;
50     private static final int REMOTE_NODE_DESCRIPTORS_TYPE = 257;
51
52
53     /* Link Descriptor QNames */
54     @VisibleForTesting
55     public static final NodeIdentifier IPV4_IFACE_NID = new NodeIdentifier(QName.create(LinkDescriptors.QNAME, "ipv4-interface-address").intern());
56     private static final NodeIdentifier IPV6_IFACE_NID = new NodeIdentifier(QName.create(LinkDescriptors.QNAME, "ipv6-interface-address").intern());
57     @VisibleForTesting
58     public static final NodeIdentifier IPV4_NEIGHBOR_NID = new NodeIdentifier(QName.create(LinkDescriptors.QNAME, "ipv4-neighbor-address").intern());
59     private static final NodeIdentifier IPV6_NEIGHBOR_NID = new NodeIdentifier(QName.create(LinkDescriptors.QNAME, "ipv6-neighbor-address").intern());
60     @VisibleForTesting
61     public static final NodeIdentifier LINK_LOCAL_NID = new NodeIdentifier(QName.create(LinkDescriptors.QNAME, "link-local-identifier").intern());
62     @VisibleForTesting
63     public static final NodeIdentifier LINK_REMOTE_NID = new NodeIdentifier(QName.create(LinkDescriptors.QNAME, "link-remote-identifier").intern());
64
65     static LinkDescriptors parseLinkDescriptors(final ByteBuf buffer) throws BGPParsingException {
66         final LinkDescriptorsBuilder builder = new LinkDescriptorsBuilder();
67         while (buffer.isReadable()) {
68             final int type = buffer.readUnsignedShort();
69             final int length = buffer.readUnsignedShort();
70             final ByteBuf value = buffer.readSlice(length);
71             LOG.trace("Parsing Link Descriptor: {}", ByteBufUtil.hexDump(value));
72             switch (type) {
73             case LINK_LR_IDENTIFIERS:
74                 builder.setLinkLocalIdentifier(value.readUnsignedInt());
75                 builder.setLinkRemoteIdentifier(value.readUnsignedInt());
76                 LOG.debug("Parsed link local {} remote {} Identifiers.", builder.getLinkLocalIdentifier(),
77                     builder.getLinkRemoteIdentifier());
78                 break;
79             case IPV4_IFACE_ADDRESS:
80                 final Ipv4InterfaceIdentifier lipv4 = new Ipv4InterfaceIdentifier(Ipv4Util.addressForByteBuf(value));
81                 builder.setIpv4InterfaceAddress(lipv4);
82                 LOG.debug("Parsed IPv4 interface address {}.", lipv4);
83                 break;
84             case IPV4_NEIGHBOR_ADDRESS:
85                 final Ipv4InterfaceIdentifier ripv4 = new Ipv4InterfaceIdentifier(Ipv4Util.addressForByteBuf(value));
86                 builder.setIpv4NeighborAddress(ripv4);
87                 LOG.debug("Parsed IPv4 neighbor address {}.", ripv4);
88                 break;
89             case IPV6_IFACE_ADDRESS:
90                 final Ipv6InterfaceIdentifier lipv6 = new Ipv6InterfaceIdentifier(Ipv6Util.addressForByteBuf(value));
91                 builder.setIpv6InterfaceAddress(lipv6);
92                 LOG.debug("Parsed IPv6 interface address {}.", lipv6);
93                 break;
94             case IPV6_NEIGHBOR_ADDRESS:
95                 final Ipv6InterfaceIdentifier ripv6 = new Ipv6InterfaceIdentifier(Ipv6Util.addressForByteBuf(value));
96                 builder.setIpv6NeighborAddress(ripv6);
97                 LOG.debug("Parsed IPv6 neighbor address {}.", ripv6);
98                 break;
99             case TlvUtil.MULTI_TOPOLOGY_ID:
100                 final TopologyIdentifier topId = new TopologyIdentifier(value.readUnsignedShort() & TlvUtil.TOPOLOGY_ID_OFFSET);
101                 builder.setMultiTopologyId(topId);
102                 LOG.debug("Parsed topology identifier {}.", topId);
103                 break;
104             default:
105                 throw new BGPParsingException("Link Descriptor not recognized, type: " + type);
106             }
107         }
108         LOG.trace("Finished parsing Link descriptors.");
109         return builder.build();
110     }
111
112     static void serializeLinkDescriptors(final LinkDescriptors descriptors, final ByteBuf buffer) {
113         if (descriptors.getLinkLocalIdentifier() != null && descriptors.getLinkRemoteIdentifier() != null) {
114             final ByteBuf identifierBuf = Unpooled.buffer();
115             identifierBuf.writeInt(descriptors.getLinkLocalIdentifier().intValue());
116             identifierBuf.writeInt(descriptors.getLinkRemoteIdentifier().intValue());
117             TlvUtil.writeTLV(LINK_LR_IDENTIFIERS, identifierBuf, buffer);
118         }
119         if (descriptors.getIpv4InterfaceAddress() != null) {
120             TlvUtil.writeTLV(IPV4_IFACE_ADDRESS, Ipv4Util.byteBufForAddress(descriptors.getIpv4InterfaceAddress()), buffer);
121         }
122         if (descriptors.getIpv4NeighborAddress() != null) {
123             TlvUtil.writeTLV(IPV4_NEIGHBOR_ADDRESS, Ipv4Util.byteBufForAddress(descriptors.getIpv4NeighborAddress()), buffer);
124         }
125         if (descriptors.getIpv6InterfaceAddress() != null) {
126             TlvUtil.writeTLV(IPV6_IFACE_ADDRESS, Ipv6Util.byteBufForAddress(descriptors.getIpv6InterfaceAddress()), buffer);
127         }
128         if (descriptors.getIpv6NeighborAddress() != null) {
129             TlvUtil.writeTLV(IPV6_NEIGHBOR_ADDRESS, Ipv6Util.byteBufForAddress(descriptors.getIpv6NeighborAddress()), buffer);
130         }
131         if (descriptors.getMultiTopologyId() != null) {
132             TlvUtil.writeTLV(TlvUtil.MULTI_TOPOLOGY_ID, Unpooled.copyShort(descriptors.getMultiTopologyId().getValue()), buffer);
133         }
134     }
135
136     static LinkDescriptors serializeLinkDescriptors(final ContainerNode descriptors) {
137         final LinkDescriptorsBuilder linkDescBuilder = new LinkDescriptorsBuilder();
138
139         if (descriptors.getChild(LINK_LOCAL_NID).isPresent() && descriptors.getChild(LINK_REMOTE_NID).isPresent()) {
140             linkDescBuilder.setLinkLocalIdentifier((Long) descriptors.getChild(LINK_LOCAL_NID).get().getValue());
141             linkDescBuilder.setLinkRemoteIdentifier((Long) descriptors.getChild(LINK_REMOTE_NID).get().getValue());
142         }
143         if (descriptors.getChild(IPV4_IFACE_NID).isPresent()) {
144             linkDescBuilder.setIpv4InterfaceAddress(new Ipv4InterfaceIdentifier((String) descriptors.getChild(IPV4_IFACE_NID).get().getValue()));
145         }
146         if (descriptors.getChild(IPV6_IFACE_NID).isPresent()) {
147             linkDescBuilder.setIpv6InterfaceAddress(new Ipv6InterfaceIdentifier((String) descriptors.getChild(IPV6_IFACE_NID).get().getValue()));
148         }
149         if (descriptors.getChild(IPV4_NEIGHBOR_NID).isPresent()) {
150             linkDescBuilder.setIpv4NeighborAddress(new Ipv4InterfaceIdentifier((String) descriptors.getChild(IPV4_NEIGHBOR_NID).get().getValue()));
151         }
152         if (descriptors.getChild(IPV6_NEIGHBOR_NID).isPresent()) {
153             linkDescBuilder.setIpv6NeighborAddress(new Ipv6InterfaceIdentifier((String) descriptors.getChild(IPV6_NEIGHBOR_NID).get().getValue()));
154         }
155         if (descriptors.getChild(TlvUtil.MULTI_TOPOLOGY_NID).isPresent()) {
156             linkDescBuilder.setMultiTopologyId(new TopologyIdentifier((Integer) descriptors.getChild(TlvUtil.MULTI_TOPOLOGY_NID).get().getValue()));
157         }
158         return linkDescBuilder.build();
159     }
160
161
162     @Override
163     public ObjectType parseTypeNlri(final ByteBuf nlri, final NlriType type, final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NodeIdentifier localdescriptor, final ByteBuf restNlri) throws BGPParsingException {
164
165         final int nodetype = restNlri.readUnsignedShort();
166         final int length = restNlri.readUnsignedShort();
167
168         RemoteNodeDescriptors remoteDescriptors = null;
169
170         if (nodetype == REMOTE_NODE_DESCRIPTORS_TYPE) {
171             remoteDescriptors = (RemoteNodeDescriptors) NodeNlriParser.parseNodeDescriptors(restNlri.readSlice(length), type, false);
172         }
173         LinkDescriptors linkdescriptor = parseLinkDescriptors(restNlri.slice());
174         LinkCaseBuilder linkbuilder = new LinkCaseBuilder();
175         LinkCase linkcase = linkbuilder.setLocalNodeDescriptors((LocalNodeDescriptors) localdescriptor).setRemoteNodeDescriptors(remoteDescriptors).setLinkDescriptors(linkdescriptor).build();
176         return linkcase;
177     }
178
179     @Override
180     public NlriType serializeTypeNlri(final CLinkstateDestination destination, final ByteBuf localdescs, final ByteBuf byteAggregator) {
181
182         final LinkCase lCase = ((LinkCase)destination.getObjectType());
183         NodeNlriParser.serializeNodeIdentifier(lCase.getLocalNodeDescriptors(), localdescs);
184         NodeNlriParser.serializeEpeNodeDescriptors(lCase.getLocalNodeDescriptors(), localdescs);
185         TlvUtil.writeTLV(LOCAL_NODE_DESCRIPTORS_TYPE, localdescs, byteAggregator);
186         final ByteBuf rdescs = Unpooled.buffer();
187         NodeNlriParser.serializeNodeIdentifier(lCase.getRemoteNodeDescriptors(), rdescs);
188         NodeNlriParser.serializeEpeNodeDescriptors(lCase.getRemoteNodeDescriptors(), rdescs);
189         TlvUtil.writeTLV(REMOTE_NODE_DESCRIPTORS_TYPE, rdescs, byteAggregator);
190         if (lCase.getLinkDescriptors() != null) {
191             LinkNlriParser.serializeLinkDescriptors(lCase.getLinkDescriptors(), byteAggregator);
192         }
193         return NlriType.Link;
194     }
195
196
197
198 }