description "Initial version. Some content originally from lisp-proto.yang";
}
+ grouping ctrl-msg-stats {
+ leaf rx-unknown {
+ type int64;
+ }
+ leaf tx-errors {
+ type int64;
+ }
+ list control-message {
+ ordered-by "user";
+ leaf msg-type {
+ type lisp-proto:message-type;
+ }
+ leaf rx-count {
+ type int64;
+ }
+ leaf tx-count {
+ type int64;
+ }
+ }
+ }
+
rpc send-map-request {
input {
uses lisp-proto:MapRequestMessage;
uses lisp-proto:MapNotifyMessage;
}
}
+
+ rpc get-stats {
+ output {
+ container control-message-stats {
+ uses ctrl-msg-stats;
+ }
+ }
+ }
+
+ rpc reset-stats {
+ }
}
return value;
}
+ public static byte getMaxValue() {
+ byte max = 0;
+ for (LispMessageEnum lme : LispMessageEnum.values()) {
+ if (lme.getValue() > max) {
+ max = lme.getValue();
+ }
+ }
+ return max;
+ }
+
public static LispMessageEnum valueOf(byte i) {
for (LispMessageEnum lme : LispMessageEnum.values()) {
if (lme.getValue() == i) {
uses EidToLocatorRecords;
}
+ typedef message-type {
+ type enumeration {
+ enum reserved {
+ value 0;
+ description
+ "Reserved";
+ }
+ enum map-request {
+ value 1;
+ description
+ "Map-Request control packet";
+ }
+ enum map-reply {
+ value 2;
+ description
+ "Map-Reply control packet";
+ }
+ enum map-register {
+ value 3;
+ description
+ "Map-Register control packet";
+ }
+ enum map-notify {
+ value 4;
+ description
+ "Map-Notify control packet";
+ }
+ enum map-referral {
+ value 6;
+ description
+ "Map-Referral control packet";
+ }
+ enum info {
+ value 7;
+ description
+ "Info control packet";
+ }
+ enum encapsulated-control-message {
+ value 8;
+ description
+ "Encapsulated control packet";
+ }
+ }
+ description
+ "Defines the LISP control message types";
+ reference "https://tools.ietf.org/html/rfc6830#section-6.1.1";
+ }
+
grouping MapRegisterMessage {
container MapRegister {
uses MapRegister;
import org.opendaylight.lispflowmapping.southbound.lisp.LispSouthboundService;
import org.opendaylight.lispflowmapping.southbound.lisp.LispXtrSouthboundService;
import org.opendaylight.lispflowmapping.type.sbplugin.IConfigLispSouthboundPlugin;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.MessageType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.transportaddress.TransportAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.LispSbService;
import org.slf4j.Logger;
private volatile boolean listenOnXtrPort = false;
private BindingAwareBroker.RpcRegistration<LispSbService> sbRpcRegistration;
private DatagramSocket xtrSocket;
+ private LispSouthboundStats statistics = new LispSouthboundStats();
public void init() {
- LOG.info("LISP (RFC6830) Mapping Service is up!");
+ LOG.info("LISP (RFC6830) southbound plugin is initializing...");
final LispSouthboundRPC sbRpcHandler = new LispSouthboundRPC(this);
sbRpcRegistration = rpcRegistry.addRpcImplementation(LispSbService.class, sbRpcHandler);
broker.registerProvider(this);
synchronized (startLock) {
- lispSouthboundService = new LispSouthboundService();
+ lispSouthboundService = new LispSouthboundService(this);
lispXtrSouthboundService = new LispXtrSouthboundService();
lispSouthboundService.setNotificationProvider(this.notificationService);
lispXtrSouthboundService.setNotificationProvider(this.notificationService);
- LOG.trace("Provider Session initialized");
if (bindingAddress == null) {
setLispAddress("0.0.0.0");
}
- LOG.info("LISP (RFC6830) Mapping Service is up!");
+ LOG.info("LISP (RFC6830) southbound plugin is up!");
}
}
lispThread = null;
xtrThread = null;
bindingAddress = null;
- LOG.info("LISP (RFC6830) Mapping Service is down!");
+ LOG.info("LISP (RFC6830) southbound plugin is down!");
try {
Thread.sleep(1100);
} catch (InterruptedException e) {
int lispReceiveTimeout = 1000;
- LOG.info("LISP (RFC6830) Mapping Service is running and listening on address: " + bindingAddress
+ LOG.info("LISP (RFC6830) southbound plugin is running and listening on address: " + bindingAddress
+ " port: " + threadSocket.getLocalPort());
try {
((address >> 0) & 0xff);
}
- public String getHelp() {
- StringBuffer help = new StringBuffer();
- help.append("---LISP Southbound Plugin---\n");
- return help.toString();
- }
-
private void startIOThread() {
if (socket != null) {
while (!socket.isClosed()) {
socket = new DatagramSocket(new InetSocketAddress(bindingAddress, LispMessage.PORT_NUM));
lispThread = new LispIoThread(socket, lispSouthboundService);
lispThread.start();
- LOG.info("LISP (RFC6830) Mapping Service Southbound Plugin is up!");
+ LOG.info("LISP (RFC6830) southbound plugin is listening for control packets!");
if (listenOnXtrPort) {
restartXtrThread();
}
xtrSocket = new DatagramSocket(new InetSocketAddress(bindingAddress, xtrPort));
xtrThread = new LispIoThread(xtrSocket, lispXtrSouthboundService);
xtrThread.start();
- LOG.info("xTR Southbound Plugin is up!");
+ LOG.info("xTR southbound plugin is up!");
} catch (SocketException e) {
LOG.warn("failed to start xtr thread: {}", ExceptionUtils.getStackTrace(e));
}
}
- public void handleSerializedLispBuffer(TransportAddress address, ByteBuffer outBuffer, String packetType) {
+ public void handleSerializedLispBuffer(TransportAddress address, ByteBuffer outBuffer, MessageType packetType) {
DatagramPacket packet = new DatagramPacket(outBuffer.array(), outBuffer.limit());
packet.setPort(address.getPort().getValue());
InetAddress ip = InetAddresses.forString(new String(address.getIpAddress().getValue()));
LOG.trace("Sending " + packetType + " on port " + address.getPort().getValue() + " to address: " + ip);
}
socket.send(packet);
+ this.statistics.incrementTx(packetType.getIntValue());
} catch (IOException e) {
LOG.warn("Failed to send " + packetType, e);
+ this.statistics.incrementTxErrors();
}
}
+ public LispSouthboundStats getStats() {
+ return statistics;
+ }
+
public void setLispAddress(String address) {
synchronized (startLock) {
if (bindingAddress != null && bindingAddress.equals(address)) {
package org.opendaylight.lispflowmapping.southbound;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.Future;
import org.opendaylight.lispflowmapping.lisp.serializer.MapNotifySerializer;
import org.opendaylight.lispflowmapping.lisp.serializer.MapRegisterSerializer;
import org.opendaylight.lispflowmapping.lisp.serializer.MapReplySerializer;
import org.opendaylight.lispflowmapping.lisp.serializer.MapRequestSerializer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.MessageType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.GetStatsOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.GetStatsOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.LispSbService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapNotifyInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapRegisterInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapReplyInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.ctrl.msg.stats.ControlMessage;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.ctrl.msg.stats.ControlMessageBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.get.stats.output.ControlMessageStatsBuilder;
+import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.slf4j.Logger;
protected static final Logger LOG = LoggerFactory.getLogger(LispSouthboundRPC.class);
- private final String MAP_NOTIFY = "MapNotify";
- private final String MAP_REPlY = "MapReply";
- private final String MAP_REQUEST = "MapRequest";
- private final String MAP_REGISTER = "MapRegister";
private final LispSouthboundPlugin lispSbPlugin;
public LispSouthboundRPC(LispSouthboundPlugin lispSbPlugin) {
LOG.trace("sendMapNotify called!!");
if (mapNotifyInput != null) {
ByteBuffer outBuffer = MapNotifySerializer.getInstance().serialize(mapNotifyInput.getMapNotify());
- lispSbPlugin.handleSerializedLispBuffer(mapNotifyInput.getTransportAddress(), outBuffer, MAP_NOTIFY);
+ lispSbPlugin.handleSerializedLispBuffer(mapNotifyInput.getTransportAddress(), outBuffer, MessageType.MapNotify);
} else {
LOG.warn("MapNotify was null");
return Futures.immediateFuture(RpcResultBuilder.<Void> failed().build());
LOG.trace("sendMapReply called!!");
if (mapReplyInput != null) {
ByteBuffer outBuffer = MapReplySerializer.getInstance().serialize(mapReplyInput.getMapReply());
- lispSbPlugin.handleSerializedLispBuffer(mapReplyInput.getTransportAddress(), outBuffer, MAP_REPlY);
+ lispSbPlugin.handleSerializedLispBuffer(mapReplyInput.getTransportAddress(), outBuffer, MessageType.MapReply);
} else {
LOG.warn("MapReply was null");
return Futures.immediateFuture(RpcResultBuilder.<Void> failed().build());
LOG.trace("sendMapRequest called!!");
if (mapRequestInput != null) {
ByteBuffer outBuffer = MapRequestSerializer.getInstance().serialize(mapRequestInput.getMapRequest());
- lispSbPlugin.handleSerializedLispBuffer(mapRequestInput.getTransportAddress(), outBuffer, MAP_REQUEST);
+ lispSbPlugin.handleSerializedLispBuffer(mapRequestInput.getTransportAddress(), outBuffer, MessageType.MapRequest);
} else {
LOG.debug("MapRequest was null");
return Futures.immediateFuture(RpcResultBuilder.<Void> failed().build());
LOG.trace("sendMapRegister called!!");
if (mapRegisterInput != null) {
ByteBuffer outBuffer = MapRegisterSerializer.getInstance().serialize(mapRegisterInput.getMapRegister());
- lispSbPlugin.handleSerializedLispBuffer(mapRegisterInput.getTransportAddress(), outBuffer, MAP_REGISTER);
+ lispSbPlugin.handleSerializedLispBuffer(mapRegisterInput.getTransportAddress(), outBuffer, MessageType.MapRegister);
} else {
LOG.debug("MapRegister was null");
return Futures.immediateFuture(RpcResultBuilder.<Void> failed().build());
}
return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
}
+
+ @Override
+ public Future<RpcResult<GetStatsOutput>> getStats() {
+ LOG.trace("getStats called!!");
+
+ RpcResultBuilder<GetStatsOutput> rpcResultBuilder;
+
+ LispSouthboundStats stats = lispSbPlugin.getStats();
+
+ if (stats == null) {
+ rpcResultBuilder = RpcResultBuilder.<GetStatsOutput>failed()
+ .withError(RpcError.ErrorType.APPLICATION, "data-missing", "No stats found");
+ } else {
+ rpcResultBuilder = RpcResultBuilder.success(createGetStatsOutput(stats));
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+ @Override
+ public Future<RpcResult<Void>> resetStats() {
+ LOG.trace("resetStats called!!");
+
+ LispSouthboundStats stats = lispSbPlugin.getStats();
+
+ if (stats == null) {
+ return Futures.immediateFuture(RpcResultBuilder.<Void> failed()
+ .withError(RpcError.ErrorType.APPLICATION, "data-missing", "No stats found")
+ .build());
+ } else {
+ stats.resetStats();
+ return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
+ }
+ }
+
+ private static GetStatsOutput createGetStatsOutput(LispSouthboundStats stats) {
+ long rxStats[] = stats.getRx();
+ long txStats[] = stats.getTx();
+
+ ControlMessageStatsBuilder cmsb = new ControlMessageStatsBuilder();
+ cmsb.setRxUnknown(stats.getRxUnknown());
+ cmsb.setTxErrors(stats.getTxErrors());
+
+ List<ControlMessage> messages = new ArrayList<ControlMessage>();
+ for (int i = 0; i <= LispSouthboundStats.MAX_LISP_TYPES; i++) {
+ if (MessageType.forValue(i) == null) {
+ continue;
+ }
+ ControlMessageBuilder cmb = new ControlMessageBuilder();
+ cmb.setMsgType(MessageType.forValue(i));
+ cmb.setRxCount(rxStats[i]);
+ cmb.setTxCount(txStats[i]);
+ messages.add(cmb.build());
+ }
+
+ cmsb.setControlMessage(messages);
+ return new GetStatsOutputBuilder().setControlMessageStats(cmsb.build()).build();
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.lispflowmapping.southbound;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.MessageType;
+
+/**
+ * Object to hold statistics about LISP southbound events
+ *
+ * @author Lorand Jakab
+ *
+ */
+public class LispSouthboundStats {
+ public final static int MAX_LISP_TYPES = getMaxMessageTypeValue();
+
+ private long rx[] = new long[MAX_LISP_TYPES + 1];
+ private long tx[] = new long[MAX_LISP_TYPES + 1];
+ private long rxUnknown = 0;
+ private long txErrors = 0;
+
+ public LispSouthboundStats() {
+ resetStats();
+ }
+
+ public void resetStats() {
+ for (int i = 0; i <= MAX_LISP_TYPES; i++) {
+ rx[i] = 0;
+ tx[i] = 0;
+ }
+ }
+
+ public long[] getRx() {
+ return rx;
+ }
+
+ public void incrementRx(int type) {
+ this.rx[type] = incrementWithWrap(rx[type]);
+ }
+
+ public long[] getTx() {
+ return tx;
+ }
+
+ public void incrementTx(int type) {
+ this.tx[type] = incrementWithWrap(tx[type]);
+ }
+
+ public long getRxUnknown() {
+ return rxUnknown;
+ }
+
+ public void incrementRxUnknown() {
+ this.rxUnknown = incrementWithWrap(rxUnknown);
+ }
+
+ public long getTxErrors() {
+ return txErrors;
+ }
+
+ public void incrementTxErrors() {
+ this.txErrors = incrementWithWrap(txErrors);
+ }
+
+ private static long incrementWithWrap(long value) {
+ if (value == Long.MAX_VALUE) {
+ return 0;
+ } else {
+ return ++value;
+ }
+ }
+
+ // TODO move this method to the appropriate helper class if we start using MessageType in other places
+ public static int getMaxMessageTypeValue() {
+ int max = 0;
+ for (MessageType mt : MessageType.values()) {
+ if (mt.getIntValue() > max) {
+ max = mt.getIntValue();
+ }
+ }
+ return max;
+ }
+}
\ No newline at end of file
import java.nio.ByteBuffer;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.lispflowmapping.southbound.LispSouthboundPlugin;
+import org.opendaylight.lispflowmapping.southbound.LispSouthboundStats;
import org.opendaylight.lispflowmapping.southbound.util.LispNotificationHelper;
import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
-import org.opendaylight.lispflowmapping.lisp.type.LispMessageEnum;
import org.opendaylight.lispflowmapping.lisp.util.ByteUtil;
import org.opendaylight.lispflowmapping.lisp.util.MapRequestUtil;
import org.opendaylight.lispflowmapping.lisp.serializer.MapNotifySerializer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.AddMappingBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.GotMapNotifyBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.GotMapReplyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.MessageType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.MapNotify;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.MapRegister;
import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev150820.MapRequest;
private NotificationProviderService notificationProvider;
protected static final Logger LOG = LoggerFactory.getLogger(LispSouthboundService.class);
+ private final LispSouthboundPlugin lispSbPlugin;
+ private LispSouthboundStats lispSbStats = null;
+
+ public LispSouthboundService(LispSouthboundPlugin lispSbPlugin) {
+ this.lispSbPlugin = lispSbPlugin;
+ if (lispSbPlugin != null) {
+ this.lispSbStats = lispSbPlugin.getStats();
+ }
+ }
+
public void setNotificationProvider(NotificationProviderService nps) {
this.notificationProvider = nps;
}
public void handlePacket(DatagramPacket packet) {
ByteBuffer inBuffer = ByteBuffer.wrap(packet.getData(), 0, packet.getLength());
int type = ByteUtil.getUnsignedByte(inBuffer, LispMessage.Pos.TYPE) >> 4;
- Object lispType = LispMessageEnum.valueOf((byte) (type));
- if (lispType == LispMessageEnum.EncapsulatedControlMessage) {
- LOG.trace("Received packet of type EncapsulatedControlMessage");
+ handleStats(type);
+ Object lispType = MessageType.forValue(type);
+ if (lispType == MessageType.EncapsulatedControlMessage) {
+ LOG.trace("Received packet of type Encapsulated Control Message");
handleEncapsulatedControlMessage(inBuffer, packet.getAddress());
- } else if (lispType == LispMessageEnum.MapRequest) {
- LOG.trace("Received packet of type MapRequest");
+ } else if (lispType == MessageType.MapRequest) {
+ LOG.trace("Received packet of type Map-Request");
handleMapRequest(inBuffer, packet.getPort());
- } else if (lispType == LispMessageEnum.MapRegister) {
- LOG.trace("Received packet of type MapRegister");
+ } else if (lispType == MessageType.MapRegister) {
+ LOG.trace("Received packet of type Map-Register");
handleMapRegister(inBuffer, packet.getAddress(), packet.getPort());
- } else if (lispType == LispMessageEnum.MapNotify) {
- LOG.trace("Received packet of type MapNotify");
+ } else if (lispType == MessageType.MapNotify) {
+ LOG.trace("Received packet of type Map-Notify");
handleMapNotify(inBuffer, packet.getAddress(), packet.getPort());
- } else if (lispType == LispMessageEnum.MapReply) {
- LOG.trace("Received packet of type MapReply");
+ } else if (lispType == MessageType.MapReply) {
+ LOG.trace("Received packet of type Map-Reply");
handleMapReply(inBuffer, packet.getAddress(), packet.getPort());
} else {
LOG.warn("Received unknown LISP control packet (type " + ((lispType != null) ? lispType : type) + ")");
throw new LispMalformedPacketException("Couldn't deserialize Map-Reply (len=" + inBuffer.capacity() + ")", re);
}
}
+
+ private void handleStats(int type) {
+ if (lispSbStats != null) {
+ if (type <= LispSouthboundStats.MAX_LISP_TYPES) {
+ lispSbStats.incrementRx(type);
+ } else {
+ lispSbStats.incrementRxUnknown();
+ }
+ }
+ }
}
super.before();
// mapResolver = context.mock(IMapResolver.class);
// mapServer = context.mock(IMapServer.class);
- testedLispService = new LispSouthboundService();
+ testedLispService = new LispSouthboundService(null);
nps = context.mock(NotificationProviderService.class);
testedLispService.setNotificationProvider(nps);
lispNotificationSaver = new ValueSaverAction<Notification>();