dd81fb645d03ed082e2ea8870faee7982dc8cc29
[bgpcep.git] / bmp / bmp-impl / src / main / java / org / opendaylight / protocol / bmp / impl / app / BmpRouterPeerImpl.java
1 /*
2  * Copyright (c) 2015 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.bmp.impl.app;
9
10 import static java.util.Objects.requireNonNull;
11 import static org.opendaylight.protocol.bmp.impl.app.TablesUtil.BMP_TABLES_QNAME;
12 import static org.opendaylight.yangtools.yang.common.QName.create;
13
14 import com.google.common.base.Preconditions;
15 import com.google.common.collect.Sets;
16 import com.google.common.util.concurrent.FutureCallback;
17 import com.google.common.util.concurrent.MoreExecutors;
18 import java.util.Locale;
19 import java.util.Set;
20 import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree;
21 import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode;
22 import org.opendaylight.mdsal.common.api.CommitInfo;
23 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
24 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
25 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
26 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
27 import org.opendaylight.protocol.bmp.impl.spi.BmpRouterPeer;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Timestamp;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.open.message.BgpParameters;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.open.message.bgp.parameters.OptionalCapabilities;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.open.message.bgp.parameters.optional.capabilities.CParameters;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.CParameters1;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.MultiprotocolCapability;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv4AddressFamily;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.UnicastSubsequentAddressFamily;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.AdjRibInType;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.Mirror;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.MirrorInformationCode;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.Peer.PeerDistinguisher;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.PeerDownNotification;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.PeerUp;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.PeerUpNotification;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.RouteMirroringMessage;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.RouteMonitoringMessage;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.Stat;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.StatsReportsMessage;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.peer.header.PeerHeader;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.peer.up.ReceivedOpen;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.peer.up.SentOpen;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev200120.stat.Tlvs;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.BmpMonitor;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.bmp.monitor.Monitor;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.peers.Peer;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.peers.peer.Mirrors;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.peers.peer.PeerSession;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.peers.peer.PostPolicyRib;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.peers.peer.PrePolicyRib;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.peers.peer.Stats;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev200120.routers.Router;
63 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
64 import org.opendaylight.yangtools.yang.binding.Notification;
65 import org.opendaylight.yangtools.yang.common.QName;
66 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
67 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
68 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
69 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
70 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
71 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
72 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
73 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
74 import org.slf4j.Logger;
75 import org.slf4j.LoggerFactory;
76
77 public final class BmpRouterPeerImpl implements BmpRouterPeer {
78
79     private static final Logger LOG = LoggerFactory.getLogger(BmpRouterPeerImpl.class);
80     private static final String TIMESTAMP_SEC = "timestamp-sec";
81
82     private static final QName PEER_ID_QNAME = create(Peer.QNAME, "peer-id").intern();
83     private static final QName PEER_TYPE_QNAME = create(Peer.QNAME, "type");
84     private static final QName PEER_ADDRESS_QNAME = create(Peer.QNAME, "address").intern();
85     private static final QName PEER_AS_QNAME = create(Peer.QNAME, "as").intern();
86     private static final QName PEER_BGP_ID_QNAME = create(Peer.QNAME, "bgp-id").intern();
87     private static final QName PEER_DISTINGUISHER_QNAME = create(Peer.QNAME, "router-distinguisher").intern();
88     private static final QName PEER_LOCAL_ADDRESS_QNAME = create(PeerSession.QNAME, "local-address").intern();
89     private static final QName PEER_LOCAL_PORT_QNAME = create(PeerSession.QNAME, "local-port").intern();
90     private static final QName PEER_REMOTE_PORT_QNAME = create(PeerSession.QNAME, "remote-port").intern();
91     private static final QName PEER_STATUS_QNAME = create(PeerSession.QNAME, "status").intern();
92     private static final QName PEER_UP_TIMESTAMP_QNAME = create(PeerSession.QNAME, TIMESTAMP_SEC).intern();
93     private static final QName PEER_STATS_TIMESTAMP_QNAME = create(Stats.QNAME, TIMESTAMP_SEC).intern();
94     private static final QName PEER_MIRROR_INFORMATION_QNAME = create(Mirrors.QNAME, "information").intern();
95     private static final QName PEER_MIRROR_TIMESTAMP_QNAME = create(Mirrors.QNAME, TIMESTAMP_SEC).intern();
96
97     private static final QName STAT0_QNAME = create(Stats.QNAME, "rejected-prefixes").intern();
98     private static final QName STAT1_QNAME = create(Stats.QNAME, "duplicate-prefix-advertisements").intern();
99     private static final QName STAT2_QNAME = create(Stats.QNAME, "duplicate-withdraws").intern();
100     private static final QName STAT3_QNAME = create(Stats.QNAME, "invalidated-cluster-list-loop").intern();
101     private static final QName STAT4_QNAME = create(Stats.QNAME, "invalidated-as-path-loop").intern();
102     private static final QName STAT5_QNAME = create(Stats.QNAME, "invalidated-originator-id").intern();
103     private static final QName STAT6_QNAME = create(Stats.QNAME, "invalidated-as-confed-loop").intern();
104     private static final QName STAT7_QNAME = create(Stats.QNAME, "adj-ribs-in-routes");
105     private static final QName STAT8_QNAME = create(Stats.QNAME, "loc-rib-routes");
106     private static final QName STAT9_QNAME = create(Stats.QNAME, "per-afi-safi-adj-rib-in-routes").intern();
107     private static final QName AF_QNAME = create(Stats.QNAME, "afi-safi").intern();
108     private static final QName COUNT_QNAME = create(Stats.QNAME, "count").intern();
109     private static final QName STAT10_QNAME = create(Stats.QNAME, "per-afi-safi-loc-rib-routes").intern();
110     private static final QName STAT11_QNAME = create(Stats.QNAME, "updates-treated-as-withdraw").intern();
111     private static final QName STAT13_QNAME = create(Stats.QNAME, "duplicate-updates").intern();
112
113     private static final TablesKey DEFAULT_TABLE =
114             new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
115
116     private static final InstanceIdentifier<PeerSession> PEER_SESSION_ID = InstanceIdentifier.builder(BmpMonitor.class)
117             .child(Monitor.class)
118             .child(Router.class)
119             .child(Peer.class)
120             .child(PeerSession.class).build();
121
122     private static final InstanceIdentifier<SentOpen> SENT_OPEN_IID = PEER_SESSION_ID.child(SentOpen.class);
123
124     private static final InstanceIdentifier<ReceivedOpen> RECEIVED_OPEN_IID = PEER_SESSION_ID.child(ReceivedOpen.class);
125
126     private final DOMTransactionChain domTxChain;
127     private final PeerId peerId;
128     private final YangInstanceIdentifier peerYangIId;
129     private final BmpRibInWriter prePolicyWriter;
130     private final BmpRibInWriter postPolicyWriter;
131     private final BindingDataObjectCodecTreeNode<SentOpen> sentOpenCodec;
132     private final BindingDataObjectCodecTreeNode<ReceivedOpen> receivedOpenCodec;
133     private boolean up = true;
134
135     private BmpRouterPeerImpl(final DOMTransactionChain domTxChain, final YangInstanceIdentifier peersYangIId,
136         final PeerId peerId, final RIBExtensionConsumerContext extensions, final PeerUpNotification peerUp,
137         final BindingCodecTree tree) {
138         this.domTxChain = requireNonNull(domTxChain);
139         this.peerId = peerId;
140         this.peerYangIId = YangInstanceIdentifier.builder(peersYangIId).nodeWithKey(Peer.QNAME, PEER_ID_QNAME,
141                 this.peerId.getValue()).build();
142         this.sentOpenCodec = tree.getSubtreeCodec(SENT_OPEN_IID);
143         this.receivedOpenCodec = tree.getSubtreeCodec(RECEIVED_OPEN_IID);
144
145         final Set<TablesKey> peerTables = setPeerTables(peerUp.getReceivedOpen());
146         final DOMDataTreeWriteTransaction wTx = this.domTxChain.newWriteOnlyTransaction();
147         wTx.put(LogicalDatastoreType.OPERATIONAL, this.peerYangIId, createPeerEntry(peerUp));
148         wTx.commit().addCallback(new FutureCallback<CommitInfo>() {
149             @Override
150             public void onSuccess(final CommitInfo result) {
151                 LOG.trace("Successful commit");
152             }
153
154             @Override
155             public void onFailure(final Throwable trw) {
156                 LOG.error("Failed commit", trw);
157             }
158         }, MoreExecutors.directExecutor());
159         this.prePolicyWriter = BmpRibInWriter.create(this.peerYangIId.node(PrePolicyRib.QNAME).node(BMP_TABLES_QNAME),
160                 this.domTxChain, extensions, peerTables, tree);
161         this.postPolicyWriter = BmpRibInWriter.create(this.peerYangIId.node(PostPolicyRib.QNAME).node(BMP_TABLES_QNAME),
162                 this.domTxChain, extensions, peerTables, tree);
163     }
164
165     static BmpRouterPeer createRouterPeer(final DOMTransactionChain domTxChain,
166             final YangInstanceIdentifier peersYangIId, final PeerUpNotification peerUp,
167             final RIBExtensionConsumerContext extensions, final BindingCodecTree tree, final PeerId peerId) {
168         return new BmpRouterPeerImpl(domTxChain, peersYangIId, peerId, extensions,
169                 peerUp, tree);
170     }
171
172     @Override
173     public void onPeerMessage(final Notification message) {
174         if (message instanceof PeerDownNotification) {
175             onPeerDown();
176         } else if (message instanceof RouteMonitoringMessage) {
177             onRouteMonitoring((RouteMonitoringMessage) message);
178         } else if (message instanceof StatsReportsMessage) {
179             onStatsReports((StatsReportsMessage) message);
180         } else if (message instanceof RouteMirroringMessage) {
181             onRouteMirror((RouteMirroringMessage) message);
182         }
183     }
184
185     private void onRouteMonitoring(final RouteMonitoringMessage routeMonitoring) {
186         if (this.up) {
187             final AdjRibInType ribType = routeMonitoring.getPeerHeader().getAdjRibInType();
188             switch (ribType) {
189                 case PrePolicy:
190                     this.prePolicyWriter.onMessage(routeMonitoring.getUpdate());
191                     break;
192                 case PostPolicy:
193                     this.postPolicyWriter.onMessage(routeMonitoring.getUpdate());
194                     break;
195                 default:
196                     break;
197             }
198         }
199     }
200
201     private synchronized void onStatsReports(final StatsReportsMessage statsReports) {
202         if (this.up) {
203             final DOMDataTreeWriteTransaction wTx = this.domTxChain.newWriteOnlyTransaction();
204             wTx.merge(LogicalDatastoreType.OPERATIONAL, this.peerYangIId.node(Stats.QNAME),
205                     createStats(statsReports, statsReports.getPeerHeader().getTimestampSec()));
206             wTx.commit().addCallback(new FutureCallback<CommitInfo>() {
207                 @Override
208                 public void onSuccess(final CommitInfo result) {
209                     LOG.trace("Successful commit");
210                 }
211
212                 @Override
213                 public void onFailure(final Throwable trw) {
214                     LOG.error("Failed commit", trw);
215                 }
216             }, MoreExecutors.directExecutor());
217         }
218     }
219
220     private synchronized void onRouteMirror(final RouteMirroringMessage mirror) {
221         final DOMDataTreeWriteTransaction wTx = this.domTxChain.newWriteOnlyTransaction();
222         wTx.merge(LogicalDatastoreType.OPERATIONAL, this.peerYangIId.node(Mirrors.QNAME),
223                 createMirrors(mirror, mirror.getPeerHeader().getTimestampSec()));
224         wTx.commit().addCallback(new FutureCallback<CommitInfo>() {
225             @Override
226             public void onSuccess(final CommitInfo result) {
227                 LOG.trace("Successful commit");
228             }
229
230             @Override
231             public void onFailure(final Throwable trw) {
232                 LOG.error("Failed commit", trw);
233             }
234         }, MoreExecutors.directExecutor());
235     }
236
237     private synchronized void onPeerDown() {
238         final DOMDataTreeWriteTransaction wTx = this.domTxChain.newWriteOnlyTransaction();
239         wTx.delete(LogicalDatastoreType.OPERATIONAL, this.peerYangIId);
240         wTx.commit().addCallback(new FutureCallback<CommitInfo>() {
241             @Override
242             public void onSuccess(final CommitInfo result) {
243                 LOG.trace("Successful commit");
244             }
245
246             @Override
247             public void onFailure(final Throwable trw) {
248                 LOG.error("Failed commit", trw);
249             }
250         }, MoreExecutors.directExecutor());
251         close();
252     }
253
254     @Override
255     public void close() {
256         Preconditions.checkState(this.up, "Already closed.");
257         this.up = false;
258     }
259
260     private static Set<TablesKey> setPeerTables(final ReceivedOpen open) {
261         final Set<TablesKey> tables = Sets.newHashSet(DEFAULT_TABLE);
262         for (final BgpParameters param : open.getBgpParameters()) {
263             for (final OptionalCapabilities optCapa : param.getOptionalCapabilities()) {
264                 final CParameters cParam = optCapa.getCParameters();
265                 if (cParam.augmentation(CParameters1.class) == null
266                         || cParam.augmentation(CParameters1.class).getMultiprotocolCapability() == null) {
267                     continue;
268                 }
269                 final MultiprotocolCapability multi = cParam.augmentation(CParameters1.class)
270                         .getMultiprotocolCapability();
271                 final TablesKey tt = new TablesKey(multi.getAfi(), multi.getSafi());
272                 tables.add(tt);
273             }
274         }
275         return tables;
276     }
277
278     private ContainerNode createPeerSessionUp(final PeerUp peerUp, final Timestamp timestamp) {
279         final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> builder = Builders.containerBuilder()
280                 .withNodeIdentifier(new NodeIdentifier(PeerSession.QNAME))
281                 .withChild(ImmutableNodes.leafNode(PEER_LOCAL_ADDRESS_QNAME,
282                         getStringIpAddress(peerUp.getLocalAddress())))
283                 .withChild(ImmutableNodes.leafNode(PEER_LOCAL_PORT_QNAME, peerUp
284                         .getLocalPort().getValue()))
285                 .withChild(ImmutableNodes.leafNode(PEER_REMOTE_PORT_QNAME, peerUp
286                         .getRemotePort().getValue()))
287                 .withChild(ImmutableNodes.leafNode(PEER_STATUS_QNAME, "up"))
288                 .withChild(ImmutableNodes.leafNode(PEER_UP_TIMESTAMP_QNAME,
289                         timestamp.getValue()));
290         if (this.receivedOpenCodec != null) {
291             builder.withChild((ContainerNode) this.receivedOpenCodec.serialize(peerUp.getReceivedOpen()));
292         }
293         if (this.sentOpenCodec != null) {
294             builder.withChild((ContainerNode) this.sentOpenCodec.serialize(peerUp.getSentOpen()));
295         }
296         return builder.build();
297     }
298
299     private MapEntryNode createPeerEntry(final PeerUpNotification peerUp) {
300         final PeerHeader peerHeader = peerUp.getPeerHeader();
301         final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder =
302                 Builders.mapEntryBuilder()
303                         .withNodeIdentifier(NodeIdentifierWithPredicates.of(Peer.QNAME, PEER_ID_QNAME,
304                                 this.peerId.getValue()))
305                         .withChild(ImmutableNodes.leafNode(PEER_ID_QNAME, this.peerId.getValue()))
306                         .withChild(ImmutableNodes.leafNode(PEER_TYPE_QNAME,
307                                 peerHeader.getType().name().toLowerCase(Locale.ENGLISH)))
308                         .withChild(ImmutableNodes.leafNode(PEER_ADDRESS_QNAME,
309                                 getStringIpAddress(peerHeader.getAddress())))
310                         .withChild(ImmutableNodes.leafNode(PEER_AS_QNAME, peerHeader.getAs().getValue()))
311                         .withChild(ImmutableNodes.leafNode(PEER_BGP_ID_QNAME, peerHeader.getBgpId().getValue()))
312                         .withChild(createPeerSessionUp(peerUp, peerHeader.getTimestampSec()))
313                         .withChild(
314                                 Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(PrePolicyRib.QNAME))
315                                         .withChild(ImmutableNodes.mapNodeBuilder(BMP_TABLES_QNAME).build()).build())
316                         .withChild(
317                                 Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(PostPolicyRib.QNAME))
318                                         .withChild(ImmutableNodes.mapNodeBuilder(BMP_TABLES_QNAME).build()).build());
319         final PeerDistinguisher pd = peerHeader.getPeerDistinguisher();
320         if (pd != null) {
321             mapEntryBuilder.withChild(ImmutableNodes.leafNode(PEER_DISTINGUISHER_QNAME, pd.getRouteDistinguisher()));
322         }
323         return mapEntryBuilder.build();
324     }
325
326     private static ContainerNode createStats(final Stat stat, final Timestamp timestamp) {
327         final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> builder =
328                 Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(Stats.QNAME));
329         builder.withChild(ImmutableNodes.leafNode(PEER_STATS_TIMESTAMP_QNAME, timestamp.getValue()));
330         final Tlvs tlvs = stat.getTlvs();
331         if (tlvs != null) {
332             statsForTlvs(tlvs, builder);
333         }
334         return builder.build();
335     }
336
337     private static void statsForTlvs(final Tlvs tlvs,
338             final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> builder) {
339         if (tlvs.getRejectedPrefixesTlv() != null) {
340             builder.withChild(ImmutableNodes.leafNode(STAT0_QNAME,
341                     tlvs.getRejectedPrefixesTlv().getCount().getValue()));
342         }
343         if (tlvs.getDuplicatePrefixAdvertisementsTlv() != null) {
344             builder.withChild(ImmutableNodes.leafNode(STAT1_QNAME,
345                     tlvs.getDuplicatePrefixAdvertisementsTlv().getCount().getValue()));
346         }
347         if (tlvs.getDuplicateWithdrawsTlv() != null) {
348             builder.withChild(ImmutableNodes.leafNode(STAT2_QNAME,
349                     tlvs.getDuplicateWithdrawsTlv().getCount().getValue()));
350         }
351         if (tlvs.getInvalidatedClusterListLoopTlv() != null) {
352             builder.withChild(ImmutableNodes.leafNode(STAT3_QNAME,
353                     tlvs.getInvalidatedClusterListLoopTlv().getCount().getValue()));
354         }
355         if (tlvs.getInvalidatedAsPathLoopTlv() != null) {
356             builder.withChild(ImmutableNodes.leafNode(STAT4_QNAME,
357                     tlvs.getInvalidatedAsPathLoopTlv().getCount().getValue()));
358         }
359         if (tlvs.getInvalidatedOriginatorIdTlv() != null) {
360             builder.withChild(ImmutableNodes.leafNode(STAT5_QNAME,
361                     tlvs.getInvalidatedOriginatorIdTlv().getCount().getValue()));
362         }
363         if (tlvs.getInvalidatedAsConfedLoopTlv() != null) {
364             builder.withChild(ImmutableNodes.leafNode(STAT6_QNAME,
365                     tlvs.getInvalidatedAsConfedLoopTlv().getCount().getValue()));
366         }
367         if (tlvs.getAdjRibsInRoutesTlv() != null) {
368             builder.withChild(ImmutableNodes.leafNode(STAT7_QNAME,
369                     tlvs.getAdjRibsInRoutesTlv().getCount().getValue()));
370         }
371         if (tlvs.getLocRibRoutesTlv() != null) {
372             builder.withChild(ImmutableNodes.leafNode(STAT8_QNAME,
373                     tlvs.getLocRibRoutesTlv().getCount().getValue()));
374         }
375         if (tlvs.getPerAfiSafiAdjRibInTlv() != null) {
376             builder.withChild(Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(STAT9_QNAME))
377                 .withChild(ImmutableNodes.mapNodeBuilder(AF_QNAME).withChild(Builders.mapEntryBuilder()
378                     .withChild(ImmutableNodes.leafNode(COUNT_QNAME,
379                             tlvs.getPerAfiSafiAdjRibInTlv().getCount().getValue()))
380                     .withNodeIdentifier(TablesUtil.toYangTablesKey(AF_QNAME,
381                             Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class))
382                     .build()).build()).build());
383         }
384         if (tlvs.getPerAfiSafiLocRibTlv() != null) {
385             builder.withChild(Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(STAT10_QNAME))
386                     .withChild(ImmutableNodes.mapNodeBuilder(AF_QNAME)
387                             .withChild(Builders.mapEntryBuilder()
388                                     .withChild(ImmutableNodes.leafNode(COUNT_QNAME,
389                                             tlvs.getPerAfiSafiLocRibTlv().getCount().getValue()))
390                                     .withNodeIdentifier(TablesUtil.toYangTablesKey(AF_QNAME,
391                                             Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class))
392                                     .build()).build()).build());
393         }
394         if (tlvs.getUpdatesTreatedAsWithdrawTlv() != null) {
395             builder.withChild(ImmutableNodes.leafNode(STAT11_QNAME,
396                     tlvs.getUpdatesTreatedAsWithdrawTlv().getCount().getValue()));
397         }
398         if (tlvs.getPrefixesTreatedAsWithdrawTlv() != null) {
399             builder.withChild(ImmutableNodes.leafNode(STAT11_QNAME,
400                     tlvs.getPrefixesTreatedAsWithdrawTlv().getCount().getValue()));
401         }
402         if (tlvs.getDuplicateUpdatesTlv() != null) {
403             builder.withChild(ImmutableNodes.leafNode(STAT13_QNAME,
404                     tlvs.getDuplicateUpdatesTlv().getCount().getValue()));
405         }
406     }
407
408     private static ContainerNode createMirrors(final Mirror mirror, final Timestamp timestamp) {
409         final DataContainerNodeBuilder<NodeIdentifier, ContainerNode> builder =
410                 Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(Mirrors.QNAME));
411         builder.withChild(ImmutableNodes.leafNode(PEER_MIRROR_INFORMATION_QNAME, toDom(MirrorInformationCode.forValue(
412                 mirror.getTlvs().getMirrorInformationTlv().getCode().getIntValue()))));
413         builder.withChild(ImmutableNodes.leafNode(PEER_MIRROR_TIMESTAMP_QNAME, timestamp.getValue()));
414         return builder.build();
415     }
416
417     private static String toDom(final MirrorInformationCode informationCode) {
418         switch (informationCode) {
419             case ErroredPdu:
420                 return "errored-pdu";
421             case MessageLost:
422                 return "message-lost";
423             default:
424                 return null;
425         }
426     }
427
428     private static String getStringIpAddress(final IpAddressNoZone ipAddress) {
429         if (ipAddress.getIpv4AddressNoZone() != null) {
430             return ipAddress.getIpv4AddressNoZone().getValue();
431         }
432         return ipAddress.getIpv6AddressNoZone().getValue();
433     }
434
435 }