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