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 / PrefixNlriSerializer.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.base.Optional;
12 import com.google.common.primitives.UnsignedBytes;
13 import io.netty.buffer.ByteBuf;
14 import io.netty.buffer.Unpooled;
15 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
16 import org.opendaylight.protocol.util.ByteBufWriteUtil;
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.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NlriType;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.OspfRouteType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.TopologyIdentifier;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.destination.CLinkstateDestination;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.PrefixCase;
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;
36
37 public final class PrefixNlriSerializer implements NlriTypeCaseSerializer {
38
39     private static final Logger LOG = LoggerFactory.getLogger(PrefixNlriSerializer.class);
40
41
42     /* Prefix Descriptor TLVs */
43     private static final int OSPF_ROUTE_TYPE = 264;
44     private static final int IP_REACHABILITY = 265;
45
46     /* Node Descriptor Type */
47     private static final int LOCAL_NODE_DESCRIPTORS_TYPE = 256;
48
49     /* Prefix Descriptor QNames */
50     @VisibleForTesting
51     public static final NodeIdentifier OSPF_ROUTE_NID = new NodeIdentifier(QName.create(PrefixDescriptors.QNAME, "ospf-route-type").intern());
52     @VisibleForTesting
53     public static final NodeIdentifier IP_REACH_NID = new NodeIdentifier(QName.create(PrefixDescriptors.QNAME, "ip-reachability-information").intern());
54
55     static void serializePrefixDescriptors(final PrefixDescriptors descriptors, final ByteBuf buffer) {
56         if (descriptors.getMultiTopologyId() != null) {
57             TlvUtil.writeTLV(TlvUtil.MULTI_TOPOLOGY_ID, Unpooled.copyShort(descriptors.getMultiTopologyId().getValue()), buffer);
58         }
59         if (descriptors.getOspfRouteType() != null) {
60             TlvUtil.writeTLV(OSPF_ROUTE_TYPE,
61                 Unpooled.wrappedBuffer(new byte[] { UnsignedBytes.checkedCast(descriptors.getOspfRouteType().getIntValue()) }), buffer);
62         }
63         if (descriptors.getIpReachabilityInformation() != null) {
64             final IpPrefix prefix = descriptors.getIpReachabilityInformation();
65
66             final ByteBuf buf;
67             if (prefix.getIpv4Prefix() != null) {
68                 buf = Unpooled.buffer(Ipv4Util.IP4_LENGTH + 1);
69                 ByteBufWriteUtil.writeMinimalPrefix(prefix.getIpv4Prefix(), buf);
70             } else if (prefix.getIpv6Prefix() != null) {
71                 buf = Unpooled.buffer(Ipv6Util.IPV6_LENGTH + 1);
72                 ByteBufWriteUtil.writeMinimalPrefix(prefix.getIpv6Prefix(), buf);
73             } else {
74                 buf = null;
75             }
76             TlvUtil.writeTLV(IP_REACHABILITY, buf, buffer);
77         }
78     }
79
80     // FIXME : use codec
81     private static int domOspfRouteTypeValue(final String ospfRouteType) {
82         switch (ospfRouteType) {
83         case "intra-area":
84             return OspfRouteType.IntraArea.getIntValue();
85         case "inter-area":
86             return OspfRouteType.InterArea.getIntValue();
87         case "external1":
88             return OspfRouteType.External1.getIntValue();
89         case "external2":
90             return OspfRouteType.External2.getIntValue();
91         case "nssa1":
92             return OspfRouteType.Nssa1.getIntValue();
93         case "nssa2":
94             return OspfRouteType.Nssa2.getIntValue();
95         default:
96             return 0;
97         }
98     }
99
100     public static PrefixDescriptors serializePrefixDescriptors(final ContainerNode prefixDesc) {
101         final PrefixDescriptorsBuilder prefixDescBuilder = new PrefixDescriptorsBuilder();
102         if (prefixDesc.getChild(TlvUtil.MULTI_TOPOLOGY_NID).isPresent()) {
103             prefixDescBuilder.setMultiTopologyId(new TopologyIdentifier((Integer) prefixDesc.getChild(TlvUtil.MULTI_TOPOLOGY_NID).get().getValue()));
104         }
105         final Optional<DataContainerChild<? extends PathArgument, ?>> ospfRoute = prefixDesc.getChild(OSPF_ROUTE_NID);
106         if (ospfRoute.isPresent()) {
107             prefixDescBuilder.setOspfRouteType(OspfRouteType.forValue(domOspfRouteTypeValue((String) ospfRoute.get().getValue())));
108         }
109         if (prefixDesc.getChild(IP_REACH_NID).isPresent()) {
110             final String prefix = (String) prefixDesc.getChild(IP_REACH_NID).get().getValue();
111
112             try {
113                 Ipv4Util.bytesForPrefixBegin(new Ipv4Prefix(prefix));
114                 prefixDescBuilder.setIpReachabilityInformation(new IpPrefix(new Ipv4Prefix(prefix)));
115             } catch (final IllegalArgumentException e) {
116                 LOG.debug("Creating Ipv6 prefix because", e);
117                 prefixDescBuilder.setIpReachabilityInformation(new IpPrefix(new Ipv6Prefix(prefix)));
118             }
119         }
120         return prefixDescBuilder.build();
121     }
122
123     @Override
124     public NlriType serializeTypeNlri(final CLinkstateDestination destination, final ByteBuf localdescs, final ByteBuf byteAggregator)  {
125         final PrefixCase pCase = ((PrefixCase)destination.getObjectType());
126         NodeNlriParser.serializeNodeIdentifier(pCase.getAdvertisingNodeDescriptors(), localdescs);
127         TlvUtil.writeTLV(LOCAL_NODE_DESCRIPTORS_TYPE, localdescs, byteAggregator);
128         if (pCase.getPrefixDescriptors() != null) {
129             serializePrefixDescriptors(pCase.getPrefixDescriptors(), byteAggregator);
130             if (pCase.getPrefixDescriptors().getIpReachabilityInformation().getIpv4Prefix() != null) {
131                 return NlriType.Ipv4Prefix;
132             } else {
133                 return NlriType.Ipv6Prefix;
134             }
135         }
136         return null;
137     }
138
139 }