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