BUG-3823 : fixed sonar issues in BGP
[bgpcep.git] / bgp / 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 org.opendaylight.protocol.bmp.impl.app.TablesUtil.BMP_TABLES_QNAME;
12 import com.google.common.base.Preconditions;
13 import java.util.HashSet;
14 import java.util.Set;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
17 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
18 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
19 import org.opendaylight.protocol.bmp.impl.spi.BmpRouterPeer;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Timestamp;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParameters;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilities;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParameters;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.MultiprotocolCapability;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev150512.AdjRibInType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev150512.PeerDownNotification;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev150512.PeerUp;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev150512.PeerUpNotification;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev150512.RouteMonitoringMessage;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev150512.Stat;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev150512.StatsReportsMessage;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev150512.peer.header.PeerHeader;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev150512.peer.up.ReceivedOpen;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev150512.peer.up.SentOpen;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.message.rev150512.stat.Tlvs;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev150512.BmpMonitor;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev150512.bmp.monitor.Monitor;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev150512.peers.Peer;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev150512.peers.peer.PeerSession;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev150512.peers.peer.PostPolicyRib;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev150512.peers.peer.PrePolicyRib;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev150512.peers.peer.Stats;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.monitor.rev150512.routers.Router;
48 import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTree;
49 import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeNode;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
51 import org.opendaylight.yangtools.yang.binding.Notification;
52 import org.opendaylight.yangtools.yang.common.QName;
53 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
54 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
55 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
56 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
57 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
58 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
59 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
60 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
61
62 public final class BmpRouterPeerImpl implements BmpRouterPeer {
63
64     private static final QName PEER_ID_QNAME = QName.cachedReference(QName.create(Peer.QNAME, "peer-id"));
65     private static final QName PEER_TYPE_QNAME = QName.cachedReference(QName.create(Peer.QNAME, "type"));
66     private static final QName PEER_ADDRESS_QNAME = QName.cachedReference(QName.create(Peer.QNAME, "address"));
67     private static final QName PEER_AS_QNAME = QName.cachedReference(QName.create(Peer.QNAME, "as"));
68     private static final QName PEER_BGP_ID_QNAME = QName.cachedReference(QName.create(Peer.QNAME, "bgp-id"));
69     private static final QName PEER_DISTINGUISHER_QNAME = QName.cachedReference(QName.create(Peer.QNAME, "router-distinguisher"));
70     private static final QName PEER_LOCAL_ADDRESS_QNAME = QName.cachedReference(QName.create(PeerSession.QNAME, "local-address"));
71     private static final QName PEER_LOCAL_PORT_QNAME = QName.cachedReference(QName.create(PeerSession.QNAME, "local-port"));
72     private static final QName PEER_REMOTE_PORT_QNAME = QName.cachedReference(QName.create(PeerSession.QNAME, "remote-port"));
73     private static final QName PEER_STATUS_QNAME = QName.cachedReference(QName.create(PeerSession.QNAME, "status"));
74     private static final QName PEER_UP_TIMESTAMP_QNAME = QName.cachedReference(QName.create(PeerSession.QNAME, "timestamp-sec"));
75     private static final QName PEER_STATS_TIMESTAMP_QNAME = QName.cachedReference(QName.create(Stats.QNAME, "timestamp-sec"));
76
77     private static final QName STAT0_QNAME = QName.cachedReference(QName.create(Stats.QNAME, "rejected-prefixes"));
78     private static final QName STAT1_QNAME = QName.cachedReference(QName.create(Stats.QNAME, "duplicate-prefix-advertisements"));
79     private static final QName STAT2_QNAME = QName.cachedReference(QName.create(Stats.QNAME, "duplicate-withdraws"));
80     private static final QName STAT3_QNAME = QName.cachedReference(QName.create(Stats.QNAME, "invalidated-cluster-list-loop"));
81     private static final QName STAT4_QNAME = QName.cachedReference(QName.create(Stats.QNAME, "invalidated-as-path-loop"));
82     private static final QName STAT5_QNAME = QName.cachedReference(QName.create(Stats.QNAME, "invalidated-originator-id"));
83     private static final QName STAT6_QNAME = QName.cachedReference(QName.create(Stats.QNAME, "invalidated-as-confed-loop"));
84     private static final QName STAT7_QNAME = QName.cachedReference(QName.create(Stats.QNAME, "adj-ribs-in-routes"));
85     private static final QName STAT8_QNAME = QName.cachedReference(QName.create(Stats.QNAME, "loc-rib-routes"));
86
87     private static final InstanceIdentifier<SentOpen> SENT_OPEN_IID = InstanceIdentifier.builder(BmpMonitor.class)
88             .child(Monitor.class)
89             .child(Router.class)
90             .child(Peer.class)
91             .child(PeerSession.class)
92             .child(SentOpen.class)
93             .build();
94     private static final InstanceIdentifier<ReceivedOpen> RECEIVED_OPEN_IID = InstanceIdentifier.builder(BmpMonitor.class)
95             .child(Monitor.class)
96             .child(Router.class)
97             .child(Peer.class)
98             .child(PeerSession.class)
99             .child(ReceivedOpen.class)
100             .build();
101
102     private final DOMTransactionChain domTxChain;
103     private final PeerId peerId;
104     private final YangInstanceIdentifier peerYangIId;
105     private final BmpRibInWriter prePolicyWriter;
106     private final BmpRibInWriter postPolicyWriter;
107     private final BindingCodecTreeNode<SentOpen> sentOpenCodec;
108     private final BindingCodecTreeNode<ReceivedOpen> receivedOpenCodec;
109     private boolean up = true;
110
111     private BmpRouterPeerImpl(final DOMTransactionChain domTxChain, final YangInstanceIdentifier peersYangIId, final PeerId peerId,
112             final RIBExtensionConsumerContext extensions, final PeerUpNotification peerUp,
113             final BindingCodecTree tree) {
114         this.domTxChain = Preconditions.checkNotNull(domTxChain);
115         this.peerId = peerId;
116         this.peerYangIId = YangInstanceIdentifier.builder(peersYangIId).nodeWithKey(Peer.QNAME, PEER_ID_QNAME, this.peerId.getValue()).build();
117
118         final Set<TablesKey> peerTables = setPeerTables(peerUp.getReceivedOpen());
119         final DOMDataWriteTransaction wTx = this.domTxChain.newWriteOnlyTransaction();
120         wTx.put(LogicalDatastoreType.OPERATIONAL, this.peerYangIId, createPeerEntry(peerUp));
121         wTx.submit();
122         this.prePolicyWriter = BmpRibInWriter.create(this.peerYangIId.node(PrePolicyRib.QNAME).node(BMP_TABLES_QNAME),
123                 this.domTxChain, extensions, peerTables, tree);
124         this.postPolicyWriter = BmpRibInWriter.create(this.peerYangIId.node(PostPolicyRib.QNAME).node(BMP_TABLES_QNAME),
125                 this.domTxChain, extensions, peerTables, tree);
126         this.sentOpenCodec = tree.getSubtreeCodec(SENT_OPEN_IID);
127         this.receivedOpenCodec = tree.getSubtreeCodec(RECEIVED_OPEN_IID);
128     }
129
130     public static BmpRouterPeer createRouterPeer(final DOMTransactionChain domTxChain,
131             final YangInstanceIdentifier peersYangIId, final PeerUpNotification peerUp,
132             final RIBExtensionConsumerContext extensions, final BindingCodecTree tree, final PeerId peerId) {
133         return new BmpRouterPeerImpl(domTxChain, peersYangIId, peerId, extensions,
134                 peerUp, tree);
135     }
136
137     @Override
138     public void onPeerMessage(final Notification message) {
139         if (message instanceof PeerDownNotification) {
140             onPeerDown();
141         } else if (message instanceof RouteMonitoringMessage) {
142             onRouteMonitoring((RouteMonitoringMessage) message);
143         } else if (message instanceof StatsReportsMessage) {
144             onStatsReports((StatsReportsMessage) message);
145         }
146     }
147
148     private void onRouteMonitoring(final RouteMonitoringMessage routeMonitoring) {
149         if (this.up) {
150             final AdjRibInType ribType = routeMonitoring.getPeerHeader().getAdjRibInType();
151             switch (ribType) {
152             case PrePolicy:
153                 this.prePolicyWriter.onMessage(routeMonitoring.getUpdate());
154                 break;
155             case PostPolicy:
156                 this.postPolicyWriter.onMessage(routeMonitoring.getUpdate());
157                 break;
158             default:
159                 break;
160             }
161         }
162     }
163
164     private void onStatsReports(final StatsReportsMessage statsReports) {
165         if (this.up) {
166             final DOMDataWriteTransaction wTx = this.domTxChain.newWriteOnlyTransaction();
167             wTx.merge(LogicalDatastoreType.OPERATIONAL, this.peerYangIId.node(Stats.QNAME),
168                     createStats(statsReports, statsReports.getPeerHeader().getTimestampSec()));
169             wTx.submit();
170         }
171     }
172
173     private void onPeerDown() {
174         final DOMDataWriteTransaction wTx = this.domTxChain.newWriteOnlyTransaction();
175         wTx.delete(LogicalDatastoreType.OPERATIONAL, this.peerYangIId);
176         wTx.submit();
177         close();
178     }
179
180     @Override
181     public PeerId getPeerId() {
182         return this.peerId;
183     }
184
185     @Override
186     public void close() {
187         Preconditions.checkState(this.up, "Already closed.");
188         this.up = false;
189     }
190
191     private Set<TablesKey> setPeerTables(final ReceivedOpen open) {
192         final Set<TablesKey> tables = new HashSet<>();
193         for (final BgpParameters param : open.getBgpParameters()) {
194             for (final OptionalCapabilities optCapa : param.getOptionalCapabilities()) {
195                 final CParameters cParam = optCapa.getCParameters();
196                 if ( cParam.getAugmentation(CParameters1.class) == null ||
197                         cParam.getAugmentation(CParameters1.class).getMultiprotocolCapability() == null ) {
198                     continue;
199                 }
200                 final MultiprotocolCapability multi = cParam.getAugmentation(CParameters1.class).getMultiprotocolCapability();
201                 final TablesKey tt = new TablesKey(multi.getAfi(), multi.getSafi());
202                 tables.add(tt);
203             }
204         }
205         return tables;
206     }
207
208     private ContainerNode createPeerSessionUp(final PeerUp peerUp,
209             final Timestamp timestamp) {
210         final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder = Builders
211                 .containerBuilder()
212                 .withNodeIdentifier(new NodeIdentifier(PeerSession.QNAME))
213                 .withChild(
214                         ImmutableNodes.leafNode(PEER_LOCAL_ADDRESS_QNAME,
215                                 getStringIpAddress(peerUp.getLocalAddress())))
216                 .withChild(
217                         ImmutableNodes.leafNode(PEER_LOCAL_PORT_QNAME, peerUp
218                                 .getLocalPort().getValue()))
219                 .withChild(
220                         ImmutableNodes.leafNode(PEER_REMOTE_PORT_QNAME, peerUp
221                                 .getRemotePort().getValue()))
222                 .withChild(ImmutableNodes.leafNode(PEER_STATUS_QNAME, "up"))
223                 .withChild(
224                         ImmutableNodes.leafNode(PEER_UP_TIMESTAMP_QNAME,
225                                 timestamp.getValue()));
226         if (this.receivedOpenCodec != null) {
227             builder.withChild(Builders.containerBuilder(
228                     (ContainerNode) this.receivedOpenCodec.serialize(peerUp
229                             .getReceivedOpen())).build());
230         }
231         if (this.sentOpenCodec != null) {
232             builder.withChild(Builders.containerBuilder(
233                     (ContainerNode) this.sentOpenCodec.serialize(peerUp
234                             .getSentOpen())).build());
235         }
236         return builder.build();
237     }
238
239     private MapEntryNode createPeerEntry(final PeerUpNotification peerUp) {
240         final PeerHeader peerHeader = peerUp.getPeerHeader();
241         final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder = Builders.mapEntryBuilder()
242                 .withNodeIdentifier(new NodeIdentifierWithPredicates(Peer.QNAME, PEER_ID_QNAME, this.peerId.getValue()))
243                 .withChild(ImmutableNodes.leafNode(PEER_ID_QNAME, this.peerId.getValue()))
244                 .withChild(ImmutableNodes.leafNode(PEER_TYPE_QNAME, peerHeader.getType().name().toLowerCase()))
245                 .withChild(ImmutableNodes.leafNode(PEER_ADDRESS_QNAME, getStringIpAddress(peerHeader.getAddress())))
246                 .withChild(ImmutableNodes.leafNode(PEER_AS_QNAME, peerHeader.getAs().getValue()))
247                 .withChild(ImmutableNodes.leafNode(PEER_BGP_ID_QNAME, peerHeader.getBgpId().getValue()))
248                 .withChild(createPeerSessionUp(peerUp, peerHeader.getTimestampSec()))
249                 .withChild(
250                         Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(PrePolicyRib.QNAME))
251                         .withChild(ImmutableNodes.mapNodeBuilder(BMP_TABLES_QNAME).build()).build())
252                 .withChild(
253                         Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(PostPolicyRib.QNAME))
254                         .withChild(ImmutableNodes.mapNodeBuilder(BMP_TABLES_QNAME).build()).build());
255         if (peerHeader.getDistinguisher() != null) {
256             mapEntryBuilder.withChild(ImmutableNodes.leafNode(PEER_DISTINGUISHER_QNAME, peerHeader.getDistinguisher().getDistinguisher()));
257         }
258         return mapEntryBuilder.build();
259     }
260
261     private ContainerNode createStats(final Stat stat, final Timestamp timestamp) {
262         final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder =
263                 Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(Stats.QNAME));
264         builder.withChild(ImmutableNodes.leafNode(PEER_STATS_TIMESTAMP_QNAME, timestamp.getValue()));
265         final Tlvs tlvs = stat.getTlvs();
266         if (tlvs != null) {
267             statsForTlvs(tlvs, builder);
268         }
269         return builder.build();
270     }
271
272     private static void statsForTlvs(final Tlvs tlvs, final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder) {
273         if (tlvs.getRejectedPrefixesTlv() != null) {
274             builder.withChild(ImmutableNodes.leafNode(STAT0_QNAME, tlvs.getRejectedPrefixesTlv().getCount().getValue()));
275         }
276         if (tlvs.getDuplicatePrefixAdvertisementsTlv() != null) {
277             builder.withChild(ImmutableNodes.leafNode(STAT1_QNAME, tlvs.getDuplicatePrefixAdvertisementsTlv().getCount().getValue()));
278         }
279         if (tlvs.getDuplicateWithdrawsTlv() != null) {
280             builder.withChild(ImmutableNodes.leafNode(STAT2_QNAME, tlvs.getDuplicateWithdrawsTlv().getCount().getValue()));
281         }
282         if (tlvs.getInvalidatedClusterListLoopTlv() != null) {
283             builder.withChild(ImmutableNodes.leafNode(STAT3_QNAME, tlvs.getInvalidatedClusterListLoopTlv().getCount().getValue()));
284         }
285         if (tlvs.getInvalidatedAsPathLoopTlv() != null) {
286             builder.withChild(ImmutableNodes.leafNode(STAT4_QNAME, tlvs.getInvalidatedAsPathLoopTlv().getCount().getValue()));
287         }
288         if (tlvs.getInvalidatedOriginatorIdTlv() != null) {
289             builder.withChild(ImmutableNodes.leafNode(STAT5_QNAME, tlvs.getInvalidatedOriginatorIdTlv().getCount().getValue()));
290         }
291         if (tlvs.getInvalidatedAsConfedLoopTlv() != null) {
292             builder.withChild(ImmutableNodes.leafNode(STAT6_QNAME, tlvs.getInvalidatedAsConfedLoopTlv().getCount().getValue()));
293         }
294         if (tlvs.getAdjRibsInRoutesTlv() != null) {
295             builder.withChild(ImmutableNodes.leafNode(STAT7_QNAME, tlvs.getAdjRibsInRoutesTlv().getCount().getValue()));
296         }
297         if (tlvs.getLocRibRoutesTlv() != null) {
298             builder.withChild(ImmutableNodes.leafNode(STAT8_QNAME, tlvs.getLocRibRoutesTlv().getCount().getValue()));
299         }
300     }
301
302     private static String getStringIpAddress(final IpAddress ipAddress) {
303         if (ipAddress.getIpv4Address() != null) {
304             return ipAddress.getIpv4Address().getValue();
305         }
306         return ipAddress.getIpv6Address().getValue();
307     }
308
309 }