[ONOS-5710] Process Map-Request msg when proxy bit is set to false
Change-Id: I0ceef00c67ab266b01dec121fe6a4fe1f3dca3e5
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispMapResolver.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispMapResolver.java
index 5784a07..fc22f80 100644
--- a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispMapResolver.java
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispMapResolver.java
@@ -15,14 +15,19 @@
*/
package org.onosproject.lisp.ctl.impl;
+import com.google.common.collect.Lists;
+import org.onosproject.lisp.msg.protocols.DefaultLispEncapsulatedControl.DefaultEcmBuilder;
import org.onosproject.lisp.msg.protocols.DefaultLispMapReply.DefaultReplyBuilder;
import org.onosproject.lisp.msg.protocols.LispEncapsulatedControl;
+import org.onosproject.lisp.msg.protocols.LispEncapsulatedControl.EcmBuilder;
+import org.onosproject.lisp.msg.protocols.LispLocatorRecord;
import org.onosproject.lisp.msg.protocols.LispMapRecord;
-import org.onosproject.lisp.msg.protocols.LispMapReply;
import org.onosproject.lisp.msg.protocols.LispMapReply.ReplyBuilder;
-import org.onosproject.lisp.msg.protocols.LispMessage;
-import org.onosproject.lisp.msg.types.LispIpAddress;
import org.onosproject.lisp.msg.protocols.LispMapRequest;
+import org.onosproject.lisp.msg.protocols.LispMapReply;
+import org.onosproject.lisp.msg.protocols.LispMessage;
+import org.onosproject.lisp.msg.types.LispAfiAddress;
+import org.onosproject.lisp.msg.types.LispIpAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,13 +43,20 @@
private static final Logger log = LoggerFactory.getLogger(LispMapResolver.class);
+ private static final int ECM_DST_PORT = 4342;
+ private static final String NO_ITR_RLOCS_MSG =
+ "No ITR RLOC is found, cannot respond to ITR.";
+ private static final String NO_ETR_RLOCS_MSG =
+ "No ETR RLOC is found, cannot relay to ETR.";
+ private static final String NO_MAP_INFO_MSG = "Map information is not found.";
+
private LispMappingDatabase mapDb = LispMappingDatabase.getInstance();
// non-instantiable (except for our Singleton)
private LispMapResolver() {
}
- public static LispMapResolver getInstance() {
+ static LispMapResolver getInstance() {
return SingletonHelper.INSTANCE;
}
@@ -54,38 +66,145 @@
* @param message encapsulated control message
* @return map-reply message
*/
- public LispMessage processMapRequest(LispMessage message) {
+ List<LispMessage> processMapRequest(LispMessage message) {
LispEncapsulatedControl ecm = (LispEncapsulatedControl) message;
LispMapRequest request = (LispMapRequest) ecm.getControlMessage();
- // build map-reply message
+ List<LispMapRecord> mapReplyRecords =
+ mapDb.getMapRecordByEidRecords(request.getEids(), true);
+
+ List<LispMapRecord> mapRequestRecords =
+ mapDb.getMapRecordByEidRecords(request.getEids(), false);
+
+ if (mapReplyRecords.size() + mapRequestRecords.size() == 0) {
+
+ // TODO: need to generate map-reply with configured native-forward action
+ log.warn(NO_MAP_INFO_MSG);
+
+ } else {
+
+ if (mapReplyRecords.size() > 0) {
+
+ List<LispMessage> mapReplies = Lists.newArrayList();
+
+ // build map-reply message based on map-request from ITR
+ ReplyBuilder replyBuilder = initMapReplyBuilder(request);
+ replyBuilder.withMapRecords(mapReplyRecords);
+
+ List<InetSocketAddress> addresses =
+ getItrAddresses(request.getItrRlocs(),
+ ecm.innerUdp().getSourcePort());
+
+ addresses.forEach(address -> {
+ if (address != null) {
+ LispMapReply reply = replyBuilder.build();
+ reply.configSender(address);
+ mapReplies.add(reply);
+ } else {
+ log.warn(NO_ITR_RLOCS_MSG);
+ }
+ });
+
+ return mapReplies;
+ }
+
+ if (mapRequestRecords.size() > 0) {
+
+ List<LispMessage> ecms = Lists.newArrayList();
+
+ // re-encapsulate encapsulated control message from ITR
+ List<InetSocketAddress> addresses =
+ getEtrAddresses(mapRequestRecords, ECM_DST_PORT);
+
+ addresses.forEach(address -> {
+ if (address != null) {
+ LispEncapsulatedControl reencapEcm = cloneEcm(ecm);
+ reencapEcm.configSender(address);
+ ecms.add(reencapEcm);
+ } else {
+ log.warn(NO_ETR_RLOCS_MSG);
+ }
+ });
+
+ return ecms;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Initializes MapReply builder without specifying map records.
+ *
+ * @param request received map request from ITR
+ * @return initialized MapReply builder
+ */
+ private ReplyBuilder initMapReplyBuilder(LispMapRequest request) {
ReplyBuilder replyBuilder = new DefaultReplyBuilder();
replyBuilder.withNonce(request.getNonce());
replyBuilder.withIsEtr(false);
replyBuilder.withIsSecurity(false);
replyBuilder.withIsProbe(request.isProbe());
- List<LispMapRecord> mapRecords = mapDb.getMapRecordByEidRecords(request.getEids());
+ return replyBuilder;
+ }
- if (mapRecords.size() == 0) {
- log.warn("Map information is not found.");
- } else {
- replyBuilder.withMapRecords(mapRecords);
+ /**
+ * Clones ECM from original ECM.
+ *
+ * @param ecm original ECM
+ * @return cloned ECM
+ */
+ private LispEncapsulatedControl cloneEcm(LispEncapsulatedControl ecm) {
+ EcmBuilder ecmBuilder = new DefaultEcmBuilder();
+ ecmBuilder.innerLispMessage(ecm.getControlMessage());
+ ecmBuilder.isSecurity(ecm.isSecurity());
+ ecmBuilder.innerIpHeader(ecm.innerIpHeader());
+ ecmBuilder.innerUdpHeader(ecm.innerUdp());
+
+ return ecmBuilder.build();
+ }
+
+ /**
+ * Obtains a collection of valid ITR addresses with a port number specified.
+ * These addresses will be used to acknowledge map-reply to ITR.
+ *
+ * @param itrRlocs a collection of ITR RLOCs
+ * @param port port number
+ * @return a collection of valid ITR addresses with a port number specified
+ */
+ private List<InetSocketAddress> getItrAddresses(List<LispAfiAddress> itrRlocs,
+ int port) {
+ List<InetSocketAddress> addresses = Lists.newArrayList();
+ for (LispAfiAddress itrRloc : itrRlocs) {
+ addresses.add(new InetSocketAddress(((LispIpAddress)
+ itrRloc).getAddress().toInetAddress(), port));
}
+ return addresses;
+ }
- LispMapReply reply = replyBuilder.build();
+ /**
+ * Obtains a collection of valid ETR addresses with a port number specified.
+ * These addresses will be used to relay map-request to ETR.
+ *
+ * @param mapRecords a collection of map records
+ * @param port port number
+ * @return a collection of valid ETR addresses with a port number specified
+ */
+ private List<InetSocketAddress> getEtrAddresses(List<LispMapRecord> mapRecords,
+ int port) {
+ List<InetSocketAddress> addresses = Lists.newArrayList();
+ for (LispMapRecord mapRecord : mapRecords) {
- if (request.getItrRlocs() != null && request.getItrRlocs().size() > 0) {
- LispIpAddress itr = (LispIpAddress) request.getItrRlocs().get(0);
- InetSocketAddress address = new InetSocketAddress(itr.getAddress().toInetAddress(),
- ecm.innerUdp().getSourcePort());
- reply.configSender(address);
- } else {
- log.warn("No ITR RLOC is found, cannot respond back to ITR.");
+ // we only select the first locator record in all cases...
+ LispLocatorRecord locatorRecord = mapRecord.getLocators().get(0);
+ if (locatorRecord != null) {
+ addresses.add(new InetSocketAddress(((LispIpAddress)
+ locatorRecord.getLocatorAfi()).getAddress()
+ .toInetAddress(), port));
+ }
}
-
- return reply;
+ return addresses;
}
/**