2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.protocol.bgp.rib.impl.stats.peer;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.base.Optional;
14 import com.google.common.base.Preconditions;
15 import com.google.common.base.Stopwatch;
16 import io.netty.channel.Channel;
17 import java.net.InetSocketAddress;
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.List;
21 import java.util.concurrent.TimeUnit;
22 import java.util.stream.Collectors;
23 import javax.annotation.Nonnull;
24 import org.opendaylight.controller.config.api.IdentityAttributeRef;
25 import org.opendaylight.controller.config.yang.bgp.rib.impl.AdvertisedAddPathTableTypes;
26 import org.opendaylight.controller.config.yang.bgp.rib.impl.AdvertizedTableTypes;
27 import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpSessionState;
28 import org.opendaylight.controller.config.yang.bgp.rib.impl.ErrorMsgs;
29 import org.opendaylight.controller.config.yang.bgp.rib.impl.ErrorReceived;
30 import org.opendaylight.controller.config.yang.bgp.rib.impl.ErrorReceivedTotal;
31 import org.opendaylight.controller.config.yang.bgp.rib.impl.ErrorSent;
32 import org.opendaylight.controller.config.yang.bgp.rib.impl.ErrorSentTotal;
33 import org.opendaylight.controller.config.yang.bgp.rib.impl.KeepAliveMsgs;
34 import org.opendaylight.controller.config.yang.bgp.rib.impl.LocalPeerPreferences;
35 import org.opendaylight.controller.config.yang.bgp.rib.impl.MessagesStats;
36 import org.opendaylight.controller.config.yang.bgp.rib.impl.Received;
37 import org.opendaylight.controller.config.yang.bgp.rib.impl.RemotePeerPreferences;
38 import org.opendaylight.controller.config.yang.bgp.rib.impl.RouteRefreshMsgs;
39 import org.opendaylight.controller.config.yang.bgp.rib.impl.Sent;
40 import org.opendaylight.controller.config.yang.bgp.rib.impl.TotalMsgs;
41 import org.opendaylight.controller.config.yang.bgp.rib.impl.UpdateMsgs;
42 import org.opendaylight.protocol.bgp.rib.impl.BGPSessionImpl;
43 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
44 import org.opendaylight.protocol.util.StatisticsUtil;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Timestamp;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.ZeroBasedCounter32;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Keepalive;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Notify;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Open;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Update;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.BgpParameters;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.OptionalCapabilities;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.message.bgp.parameters.optional.capabilities.CParameters;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.CParameters1;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.RouteRefresh;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.MultiprotocolCapability;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.add.path.capability.AddressFamilies;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpId;
63 import org.opendaylight.yangtools.yang.binding.Notification;
64 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
65 import org.opendaylight.yangtools.yang.common.QName;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
69 public final class BGPSessionStatsImpl implements BGPSessionStats {
70 private static final Logger LOG = LoggerFactory.getLogger(BGPSessionStatsImpl.class);
72 private final Stopwatch sessionStopwatch;
73 private final BgpSessionState stats;
74 private final BGPSessionImpl session;
75 private final TotalMsgs totalMsgs = new TotalMsgs();
76 private final KeepAliveMsgs kaMsgs = new KeepAliveMsgs();
77 private final UpdateMsgs updMsgs = new UpdateMsgs();
78 private final RouteRefreshMsgs rrMsgs = new RouteRefreshMsgs();
79 private final ErrorMsgs errMsgs = new ErrorMsgs();
80 private final ErrorSentTotal errMsgsSentTotal = new ErrorSentTotal();
81 private final ErrorReceivedTotal errMsgsRecvTotal = new ErrorReceivedTotal();
82 private static final ZeroBasedCounter32 INITIAL_COUNTER = new ZeroBasedCounter32(0L);
84 public BGPSessionStatsImpl(@Nonnull final BGPSessionImpl session, @Nonnull final Open remoteOpen, final int holdTimerValue, final int keepAlive, @Nonnull final Channel channel,
85 @Nonnull final Optional<BGPSessionPreferences> localPreferences, @Nonnull final Collection<BgpTableType> tableTypes, @Nonnull final List<AddressFamilies> addPathTypes) {
86 this.session = session;
87 this.sessionStopwatch = Stopwatch.createUnstarted();
88 this.stats = new BgpSessionState();
89 this.stats.setHoldtimeCurrent(holdTimerValue);
90 this.stats.setKeepaliveCurrent(keepAlive);
91 this.stats.setLocalPeerPreferences(setLocalPeerPref(remoteOpen, channel, tableTypes, addPathTypes));
92 this.stats.setRemotePeerPreferences(setRemotePeerPref(channel, localPreferences));
93 this.errMsgs.setErrorReceivedTotal(this.errMsgsRecvTotal);
94 this.errMsgs.setErrorSentTotal(this.errMsgsSentTotal);
95 this.errMsgs.setErrorReceived(new ArrayList<>());
96 this.errMsgs.setErrorSent(new ArrayList<>());
100 private static Received newReceivedInstance() {
101 final Received recv = new Received();
102 recv.setCount(INITIAL_COUNTER);
106 private static Sent newSentInstance() {
107 final Sent sent = new Sent();
108 sent.setCount(INITIAL_COUNTER);
112 private static void updateReceivedMsg(final Received received) {
113 requireNonNull(received);
114 final long count = received.getCount() == null ? 0L : received.getCount().getValue();
115 received.setCount(new ZeroBasedCounter32(count + 1));
116 received.setTimestamp(new Timestamp(StatisticsUtil.getCurrentTimestampInSeconds()));
119 private static void updateSentMsg(final Sent sent) {
120 requireNonNull(sent);
121 final long count = sent.getCount() == null ? 0L : sent.getCount().getValue();
122 sent.setCount(new ZeroBasedCounter32(count + 1));
123 sent.setTimestamp(new Timestamp(StatisticsUtil.getCurrentTimestampInSeconds()));
126 private static AdvertizedTableTypes addTableType(final BgpTableType type) {
127 requireNonNull(type);
128 final AdvertizedTableTypes att = new AdvertizedTableTypes();
129 final QName afi = BindingReflections.findQName(type.getAfi()).intern();
130 final QName safi = BindingReflections.findQName(type.getSafi()).intern();
131 att.setAfi(new IdentityAttributeRef(afi.toString()));
132 att.setSafi(new IdentityAttributeRef(safi.toString()));
136 private static AdvertisedAddPathTableTypes addAddPathTableType(final AddressFamilies addressFamilies) {
137 requireNonNull(addressFamilies);
138 final AdvertisedAddPathTableTypes att = new AdvertisedAddPathTableTypes();
139 att.setAfi(new IdentityAttributeRef(BindingReflections.findQName(addressFamilies.getAfi()).intern().toString()));
140 att.setSafi(new IdentityAttributeRef(BindingReflections.findQName(addressFamilies.getSafi()).intern().toString()));
141 att.setSendReceive(addressFamilies.getSendReceive());
145 private static RemotePeerPreferences setRemotePeerPref(final Channel channel, final Optional<BGPSessionPreferences> localPreferences) {
146 requireNonNull(channel);
147 final RemotePeerPreferences pref = new RemotePeerPreferences();
148 final InetSocketAddress isa = (InetSocketAddress) channel.localAddress();
149 pref.setHost(IpAddressBuilder.getDefaultInstance(isa.getAddress().getHostAddress()));
150 pref.setPort(new PortNumber(isa.getPort()));
151 final List<AdvertizedTableTypes> tt = new ArrayList<>();
152 final List<AdvertisedAddPathTableTypes> attList = new ArrayList<>();
153 if (localPreferences.isPresent()) {
154 final BGPSessionPreferences localPref = localPreferences.get();
155 pref.setBgpId(localPref.getBgpId());
156 pref.setAs(localPref.getMyAs());
157 pref.setHoldtimer(localPref.getHoldTime());
158 if (localPref.getParams() != null) {
159 for (final BgpParameters param : localPref.getParams()) {
160 for (final OptionalCapabilities capa : param.getOptionalCapabilities()) {
161 final CParameters cParam = capa.getCParameters();
162 final CParameters1 capabilities = cParam.getAugmentation(CParameters1.class);
163 if (capabilities != null) {
164 final MultiprotocolCapability mc = capabilities.getMultiprotocolCapability();
166 final AdvertizedTableTypes att = new AdvertizedTableTypes();
167 att.setAfi(new IdentityAttributeRef(BindingReflections.findQName(mc.getAfi()).intern().toString()));
168 att.setSafi(new IdentityAttributeRef(BindingReflections.findQName(mc.getSafi()).intern().toString()));
171 if (capabilities.getGracefulRestartCapability() != null) {
172 pref.setGrCapability(true);
174 if (capabilities.getAddPathCapability() != null) {
175 // FIXME: add path capability is deprecated, replaced by addPathTableTypes
176 pref.setAddPathCapability(true);
178 final List<AdvertisedAddPathTableTypes> addPathTableTypeList = capabilities.getAddPathCapability()
179 .getAddressFamilies()
181 .map(BGPSessionStatsImpl::addAddPathTableType)
182 .collect(Collectors.toList());
183 attList.addAll(addPathTableTypeList);
185 if (capabilities.getRouteRefreshCapability() != null) {
186 pref.setRouteRefreshCapability(true);
189 if (cParam.getAs4BytesCapability() != null) {
190 pref.setFourOctetAsCapability(true);
192 if (cParam.getBgpExtendedMessageCapability() != null) {
193 pref.setBgpExtendedMessageCapability(true);
199 pref.setAdvertizedTableTypes(tt);
200 pref.setAdvertisedAddPathTableTypes(attList);
204 private static LocalPeerPreferences setLocalPeerPref(final Open remoteOpen, final Channel channel, final Collection<BgpTableType> tableTypes,
205 final List<AddressFamilies> addPathTypes) {
206 requireNonNull(remoteOpen);
207 requireNonNull(channel);
208 final LocalPeerPreferences pref = new LocalPeerPreferences();
209 final InetSocketAddress isa = (InetSocketAddress) channel.remoteAddress();
210 pref.setHost(IpAddressBuilder.getDefaultInstance(isa.getAddress().getHostAddress()));
211 pref.setPort(new PortNumber(isa.getPort()));
212 pref.setBgpId(new BgpId(remoteOpen.getBgpIdentifier()));
213 pref.setAs(new AsNumber(remoteOpen.getMyAsNumber().longValue()));
214 pref.setHoldtimer(remoteOpen.getHoldTimer());
216 final List<AdvertizedTableTypes> tt = tableTypes.stream().map(BGPSessionStatsImpl::addTableType).collect(Collectors.toList());
217 final List<AdvertisedAddPathTableTypes> addPathTableTypeList = addPathTypes.stream().map(BGPSessionStatsImpl::addAddPathTableType)
218 .collect(Collectors.toList());
220 if (remoteOpen.getBgpParameters() != null) {
221 for (final BgpParameters param : remoteOpen.getBgpParameters()) {
222 for (final OptionalCapabilities capa : param.getOptionalCapabilities()) {
223 final CParameters cParam = capa.getCParameters();
224 final CParameters1 capabilities = cParam.getAugmentation(CParameters1.class);
225 if (cParam.getAs4BytesCapability() != null) {
226 pref.setFourOctetAsCapability(true);
228 if (capabilities != null) {
229 if (capabilities.getGracefulRestartCapability() != null) {
230 pref.setGrCapability(true);
232 // FIXME: add-path-capability is deprecated in Boron
233 if (capabilities.getAddPathCapability() != null) {
234 pref.setAddPathCapability(true);
236 if (capabilities.getRouteRefreshCapability() != null) {
237 pref.setRouteRefreshCapability(true);
240 if (cParam.getBgpExtendedMessageCapability() != null) {
241 pref.setBgpExtendedMessageCapability(true);
247 pref.setAdvertizedTableTypes(tt);
248 pref.setAdvertisedAddPathTableTypes(addPathTableTypeList);
252 private void initMsgs() {
253 this.totalMsgs.setReceived(newReceivedInstance());
254 this.totalMsgs.setSent(newSentInstance());
255 this.kaMsgs.setReceived(newReceivedInstance());
256 this.kaMsgs.setSent(newSentInstance());
257 this.updMsgs.setReceived(newReceivedInstance());
258 this.updMsgs.setSent(newSentInstance());
259 this.rrMsgs.setReceived(newReceivedInstance());
260 this.rrMsgs.setSent(newSentInstance());
261 this.errMsgsSentTotal.setCount(INITIAL_COUNTER);
262 this.errMsgsRecvTotal.setCount(INITIAL_COUNTER);
263 this.errMsgs.getErrorSent().clear();
264 this.errMsgs.getErrorReceived().clear();
267 public void startSessionStopwatch() {
268 this.sessionStopwatch.start();
271 private void updateSentMsgTotal() {
272 updateSentMsg(this.totalMsgs.getSent());
275 private void updateReceivedMsgTotal() {
276 updateReceivedMsg(this.totalMsgs.getReceived());
279 private void updateReceivedMsgKA() {
280 updateReceivedMsg(this.kaMsgs.getReceived());
283 public void updateSentMsgKA() {
284 updateSentMsg(this.kaMsgs.getSent());
287 private void updateSentMsgUpd() {
288 updateSentMsg(this.updMsgs.getSent());
291 private void updateReceivedMsgUpd() {
292 updateReceivedMsg(this.updMsgs.getReceived());
295 private void updateSentMsgRR() {
296 updateSentMsg(this.rrMsgs.getSent());
299 private void updateReceivedMsgRR() {
300 updateReceivedMsg(this.rrMsgs.getReceived());
303 private void updateReceivedMsgErr(@Nonnull final Notify error) {
304 requireNonNull(error);
305 final List<ErrorReceived> errList = this.errMsgs.getErrorReceived();
306 ErrorReceived received = null;
307 for (ErrorReceived err : errList) {
308 if (err.getErrorCode().equals(error.getErrorCode()) && err.getErrorSubcode().equals(error.getErrorSubcode())) {
313 if (null == received) {
314 received = new ErrorReceived();
315 received.setErrorCode(error.getErrorCode());
316 received.setErrorSubcode(error.getErrorSubcode());
317 received.setCount(INITIAL_COUNTER);
318 errList.add(received);
320 received.setCount(new ZeroBasedCounter32(received.getCount().getValue() + 1));
321 final Timestamp curTimestamp = new Timestamp(StatisticsUtil.getCurrentTimestampInSeconds());
322 received.setTimestamp(curTimestamp);
323 this.errMsgsRecvTotal.setCount(new ZeroBasedCounter32(this.errMsgsRecvTotal.getCount().getValue() + 1));
324 this.errMsgsRecvTotal.setTimestamp(curTimestamp);
327 private void updateSentMsgErr(@Nonnull final Notify error) {
328 requireNonNull(error);
329 final List<ErrorSent> errList = this.errMsgs.getErrorSent();
330 ErrorSent sent = null;
331 for (ErrorSent err : errList) {
332 if (err.getErrorCode().equals(error.getErrorCode()) && err.getErrorSubcode().equals(error.getErrorSubcode())) {
338 sent = new ErrorSent();
339 sent.setErrorCode(error.getErrorCode());
340 sent.setErrorSubcode(error.getErrorSubcode());
341 sent.setCount(INITIAL_COUNTER);
344 sent.setCount(new ZeroBasedCounter32(sent.getCount().getValue() + 1));
345 final Timestamp curTimestamp = new Timestamp(StatisticsUtil.getCurrentTimestampInSeconds());
346 sent.setTimestamp(curTimestamp);
347 this.errMsgsSentTotal.setCount(new ZeroBasedCounter32(this.errMsgsSentTotal.getCount().getValue() + 1));
348 this.errMsgsSentTotal.setTimestamp(curTimestamp);
352 public BgpSessionState getBgpSessionState() {
353 final MessagesStats msgs = new MessagesStats();
354 msgs.setTotalMsgs(this.totalMsgs);
355 msgs.setErrorMsgs(this.errMsgs);
356 msgs.setKeepAliveMsgs(this.kaMsgs);
357 msgs.setUpdateMsgs(this.updMsgs);
358 msgs.setRouteRefreshMsgs(this.rrMsgs);
359 this.stats.setSessionDuration(StatisticsUtil.formatElapsedTime(this.sessionStopwatch.elapsed(TimeUnit.SECONDS)));
360 this.stats.setSessionState(this.session.getState().toString());
361 this.stats.setMessagesStats(msgs);
366 public void resetBgpSessionStats() {
370 public void updateReceivedMsg(Notification msg) {
371 LOG.trace("Updating received BGP session message count..");
372 this.updateReceivedMsgTotal();
373 if (msg instanceof Notify) {
374 this.updateReceivedMsgErr((Notify) msg);
375 } else if (msg instanceof Keepalive) {
376 this.updateReceivedMsgKA();
377 } else if (msg instanceof RouteRefresh) {
378 this.updateReceivedMsgRR();
379 } else if (msg instanceof Update) {
380 this.updateReceivedMsgUpd();
384 public void updateSentMsg(Notification msg) {
385 LOG.trace("Updating sent BGP session message count..");
386 this.updateSentMsgTotal();
387 if (msg instanceof Update) {
388 this.updateSentMsgUpd();
389 } else if (msg instanceof Notify) {
390 this.updateSentMsgErr((Notify) msg);
391 } else if (msg instanceof RouteRefresh) {
392 this.updateSentMsgRR();