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