Support Solicit-Map-Request (SMR) message for updated MapRegister
Change-Id: I9d0865d569557c904b161d124b4616111f0f9807
diff --git a/protocols/lisp/api/src/main/java/org/onosproject/lisp/ctl/AbstractLispRouter.java b/protocols/lisp/api/src/main/java/org/onosproject/lisp/ctl/AbstractLispRouter.java
index a2c6232..44c865a 100644
--- a/protocols/lisp/api/src/main/java/org/onosproject/lisp/ctl/AbstractLispRouter.java
+++ b/protocols/lisp/api/src/main/java/org/onosproject/lisp/ctl/AbstractLispRouter.java
@@ -16,8 +16,10 @@
package org.onosproject.lisp.ctl;
import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
import io.netty.channel.Channel;
import org.onlab.packet.IpAddress;
+import org.onosproject.lisp.msg.protocols.LispEidRecord;
import org.onosproject.lisp.msg.protocols.LispMessage;
import org.onosproject.net.Device;
import org.slf4j.Logger;
@@ -25,6 +27,7 @@
import java.net.InetSocketAddress;
import java.net.SocketAddress;
+import java.util.List;
/**
* An abstract representation of a LISP router.
@@ -45,6 +48,7 @@
private boolean subscribed;
private LispRouterId routerId;
private LispRouterAgent agent;
+ private List<LispEidRecord> records;
/**
* A default constructor.
@@ -89,7 +93,6 @@
return connected;
}
-
@Override
public final boolean isSubscribed() {
return subscribed;
@@ -131,6 +134,7 @@
@Override
public final boolean connectRouter() {
+ setConnected(true);
return this.agent.addConnectedRouter(routerId, this);
}
@@ -141,6 +145,16 @@
}
@Override
+ public List<LispEidRecord> getEidRecords() {
+ return records;
+ }
+
+ @Override
+ public void setEidRecords(List<LispEidRecord> records) {
+ this.records = ImmutableList.copyOf(records);
+ }
+
+ @Override
public String toString() {
StringBuilder sb = new StringBuilder();
diff --git a/protocols/lisp/api/src/main/java/org/onosproject/lisp/ctl/LispRouter.java b/protocols/lisp/api/src/main/java/org/onosproject/lisp/ctl/LispRouter.java
index 5b32853..0ccbdb7 100644
--- a/protocols/lisp/api/src/main/java/org/onosproject/lisp/ctl/LispRouter.java
+++ b/protocols/lisp/api/src/main/java/org/onosproject/lisp/ctl/LispRouter.java
@@ -17,9 +17,12 @@
import io.netty.channel.Channel;
import org.onlab.packet.IpAddress;
+import org.onosproject.lisp.msg.protocols.LispEidRecord;
import org.onosproject.lisp.msg.protocols.LispMessage;
import org.onosproject.net.Device;
+import java.util.List;
+
/**
* Represents to provider facing side of a router.
*/
@@ -105,6 +108,20 @@
void setSubscribed(boolean subscribed);
/**
+ * Obtains a collection of EID records that associated with this router.
+ *
+ * @return a collection EID records that associated with this router
+ */
+ List<LispEidRecord> getEidRecords();
+
+ /**
+ * Associates the EID records to this router.
+ *
+ * @param records a collection of EID records
+ */
+ void setEidRecords(List<LispEidRecord> records);
+
+ /**
* Sets the LISP agent to be used. This method can only be invoked once.
*
* @param agent the agent to set
diff --git a/protocols/lisp/api/src/main/java/org/onosproject/lisp/ctl/LispRouterFactory.java b/protocols/lisp/api/src/main/java/org/onosproject/lisp/ctl/LispRouterFactory.java
index db7e583..790ee8c 100644
--- a/protocols/lisp/api/src/main/java/org/onosproject/lisp/ctl/LispRouterFactory.java
+++ b/protocols/lisp/api/src/main/java/org/onosproject/lisp/ctl/LispRouterFactory.java
@@ -15,9 +15,13 @@
*/
package org.onosproject.lisp.ctl;
+import com.google.common.collect.Maps;
import org.onlab.packet.IpAddress;
import org.slf4j.Logger;
+import java.util.Collection;
+import java.util.Map;
+
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -29,6 +33,7 @@
private final Logger log = getLogger(getClass());
private LispRouterAgent agent;
+ private Map<LispRouterId, LispRouter> routerMap = Maps.newConcurrentMap();
// non-instantiable (except for our Singleton)
private LispRouterFactory() {
@@ -65,13 +70,28 @@
/**
* Returns a LISP router instance.
*
- * @param routerId LISP router identifier
+ * @param ipAddress IP address of LISP router
* @return LISP router instance
*/
- public LispRouter getRouterInstance(IpAddress routerId) {
- LispRouter router = new DefaultLispRouter(new LispRouterId(routerId));
- router.setAgent(agent);
- return router;
+ public LispRouter getRouterInstance(IpAddress ipAddress) {
+ LispRouterId routerId = new LispRouterId(ipAddress);
+ if (!routerMap.containsKey(routerId)) {
+ LispRouter router = new DefaultLispRouter(routerId);
+ router.setAgent(agent);
+ routerMap.put(routerId, router);
+ return router;
+ } else {
+ return routerMap.get(routerId);
+ }
+ }
+
+ /**
+ * Returns all LISP routers.
+ *
+ * @return all LISP routers
+ */
+ public Collection<LispRouter> getRouters() {
+ return routerMap.values();
}
/**
diff --git a/protocols/lisp/api/src/test/java/org/onosproject/lisp/ctl/LispRouterAdapter.java b/protocols/lisp/api/src/test/java/org/onosproject/lisp/ctl/LispRouterAdapter.java
index c693447..0572035 100644
--- a/protocols/lisp/api/src/test/java/org/onosproject/lisp/ctl/LispRouterAdapter.java
+++ b/protocols/lisp/api/src/test/java/org/onosproject/lisp/ctl/LispRouterAdapter.java
@@ -15,11 +15,15 @@
*/
package org.onosproject.lisp.ctl;
+import com.google.common.collect.ImmutableList;
import io.netty.channel.Channel;
import org.onlab.packet.IpAddress;
+import org.onosproject.lisp.msg.protocols.LispEidRecord;
import org.onosproject.lisp.msg.protocols.LispMessage;
import org.onosproject.net.Device;
+import java.util.List;
+
/**
* Test adapter for the LISP router interface.
*/
@@ -83,6 +87,16 @@
}
@Override
+ public List<LispEidRecord> getEidRecords() {
+ return ImmutableList.of();
+ }
+
+ @Override
+ public void setEidRecords(List<LispEidRecord> records) {
+
+ }
+
+ @Override
public void setAgent(LispRouterAgent agent) {
}
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispChannelHandler.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispChannelHandler.java
index ac72d57..1e3be19 100644
--- a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispChannelHandler.java
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispChannelHandler.java
@@ -120,6 +120,20 @@
if (msg instanceof LispEncapsulatedControl) {
LispMessage innerMsg = extractLispMessage((LispEncapsulatedControl) msg);
if (innerMsg instanceof LispMapRequest) {
+
+ IpAddress xtrAddress = valueOf(innerMsg.getSender().getAddress());
+
+ router = routerFactory.getRouterInstance(xtrAddress);
+
+ if (!router.isConnected()) {
+ router.setChannel(ctx.channel());
+ router.connectRouter();
+ }
+
+ router.setEidRecords(((LispMapRequest) innerMsg).getEids());
+ router.setSubscribed(true);
+ router.handleMessage(innerMsg);
+
LispMapResolver mapResolver = LispMapResolver.getInstance();
List<LispMessage> lispMessages =
mapResolver.processMapRequest(msg);
@@ -136,8 +150,12 @@
LispMapRegister register = (LispMapRegister) msg;
IpAddress xtrAddress = valueOf(register.getSender().getAddress());
router = routerFactory.getRouterInstance(xtrAddress);
- router.setChannel(ctx.channel());
- router.connectRouter();
+
+ if (!router.isConnected()) {
+ router.setChannel(ctx.channel());
+ router.connectRouter();
+ }
+
router.handleMessage(register);
LispMapServer mapServer = LispMapServer.getInstance();
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispControllerImpl.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispControllerImpl.java
index 95af771..573db1b 100644
--- a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispControllerImpl.java
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispControllerImpl.java
@@ -87,6 +87,11 @@
"default value is 1")
private int lispAuthKeyId = DEFAULT_LISP_AUTH_KEY_ID;
+ @Property(name = "enableSmr", boolValue = false,
+ label = "Enable to send SMR(Solicit Map Request) by map server; " +
+ "By default SMR is not activated")
+ private boolean enableSmr = false;
+
ExecutorService executorMessages =
newFixedThreadPool(4, groupedThreads("onos/lisp", "event-stats-%d", log));
@@ -169,6 +174,16 @@
log.info("Configured. LISP authentication method is configured to {}", lispAuthKeyId);
}
authConfig.updateLispAuthKeyId(lispAuthKeyId);
+
+ Boolean enableSmr = Tools.isPropertyEnabled(properties, "enableSmr");
+ if (enableSmr == null) {
+ log.info("Enable SMR is not configured, " +
+ "using current value of {}", this.enableSmr);
+ } else {
+ this.enableSmr = enableSmr;
+ log.info("Configured. Sending SMR through map server is {}",
+ this.enableSmr ? "enabled" : "disabled");
+ }
}
@Override
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispMapServer.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispMapServer.java
index 5e4d35a..ae766ba 100644
--- a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispMapServer.java
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispMapServer.java
@@ -15,12 +15,17 @@
*/
package org.onosproject.lisp.ctl.impl;
+import com.google.common.collect.ImmutableList;
import org.onlab.packet.IpAddress;
+import org.onosproject.lisp.ctl.LispRouter;
+import org.onosproject.lisp.ctl.LispRouterFactory;
+import org.onosproject.lisp.ctl.impl.util.LispMapUtil;
import org.onosproject.lisp.msg.authentication.LispAuthenticationConfig;
import org.onosproject.lisp.msg.protocols.DefaultLispInfoReply.DefaultInfoReplyBuilder;
import org.onosproject.lisp.msg.protocols.DefaultLispInfoRequest.DefaultInfoRequestBuilder;
import org.onosproject.lisp.msg.protocols.DefaultLispMapNotify.DefaultNotifyBuilder;
import org.onosproject.lisp.msg.protocols.DefaultLispMapRegister.DefaultRegisterBuilder;
+import org.onosproject.lisp.msg.protocols.DefaultLispMapRequest.DefaultRequestBuilder;
import org.onosproject.lisp.msg.protocols.LispEidRecord;
import org.onosproject.lisp.msg.protocols.LispInfoReply;
import org.onosproject.lisp.msg.protocols.LispInfoReply.InfoReplyBuilder;
@@ -28,8 +33,11 @@
import org.onosproject.lisp.msg.protocols.LispInfoRequest.InfoRequestBuilder;
import org.onosproject.lisp.msg.protocols.LispMapNotify;
import org.onosproject.lisp.msg.protocols.LispMapNotify.NotifyBuilder;
+import org.onosproject.lisp.msg.protocols.LispMapRecord;
import org.onosproject.lisp.msg.protocols.LispMapRegister;
import org.onosproject.lisp.msg.protocols.LispMapRegister.RegisterBuilder;
+import org.onosproject.lisp.msg.protocols.LispMapRequest;
+import org.onosproject.lisp.msg.protocols.LispMapRequest.RequestBuilder;
import org.onosproject.lisp.msg.protocols.LispMessage;
import org.onosproject.lisp.msg.types.LispAfiAddress;
import org.onosproject.lisp.msg.types.LispIpv4Address;
@@ -43,6 +51,8 @@
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
import static org.onlab.packet.IpAddress.valueOf;
import static org.onosproject.lisp.msg.authentication.LispAuthenticationKeyEnum.valueOf;
@@ -63,6 +73,7 @@
private static final String FAILED_TO_FORMULATE_NAT_MSG =
"Fails during formulate NAT address.";
+ private boolean enableSmr = false;
private LispMappingDatabase mapDb = LispMappingDatabase.getInstance();
private LispAuthenticationConfig authConfig = LispAuthenticationConfig.getInstance();
@@ -76,6 +87,15 @@
}
/**
+ * Enable LISP Map server sends SMR(Solicit Map Request) message.
+ *
+ * @param enable whether enable or disable sending SMR
+ */
+ public void enableSmr(boolean enable) {
+ this.enableSmr = enable;
+ }
+
+ /**
* Handles map-register message and replies with map-notify message.
*
* @param message map-register message
@@ -95,7 +115,19 @@
new LispEidRecord(mapRecord.getMaskLength(),
mapRecord.getEidPrefixAfi());
- mapDb.putMapRecord(eidRecord, mapRecord, register.isProxyMapReply());
+ LispMapRecord oldMapRecord = mapDb.getMapRecordByEidRecord(eidRecord,
+ register.isProxyMapReply());
+ if (oldMapRecord == null) {
+ mapDb.putMapRecord(eidRecord, mapRecord, register.isProxyMapReply());
+ } else {
+ if (oldMapRecord.getMapVersionNumber() <= mapRecord.getMapVersionNumber()) {
+ mapDb.putMapRecord(eidRecord, mapRecord, register.isProxyMapReply());
+
+ if (enableSmr) {
+ sendSmrMessage(eidRecord);
+ }
+ }
+ }
});
// we only acknowledge back to ETR when want-map-notify bit is set to true
@@ -220,6 +252,50 @@
}
/**
+ * Sends SMR (Solicit Map Request) to their subscribers.
+ *
+ * @param eidRecord the updated EID
+ */
+ private void sendSmrMessage(LispEidRecord eidRecord) {
+
+ RequestBuilder builder = new DefaultRequestBuilder();
+
+ LispAfiAddress msAddress = null;
+ try {
+ msAddress = new LispIpv4Address(IpAddress.valueOf(InetAddress.getLocalHost()));
+ } catch (UnknownHostException e) {
+ log.warn("Source EID is not found, {}", e.getMessage());
+ }
+
+ LispMapRequest msg = builder.withIsSmr(true)
+ .withIsSmrInvoked(true)
+ .withIsProbe(false)
+ .withIsPitr(false)
+ .withIsAuthoritative(false)
+ .withIsMapDataPresent(false)
+ .withSourceEid(msAddress)
+ .withEidRecords(ImmutableList.of(eidRecord))
+ .build();
+
+ LispRouterFactory routerFactory = LispRouterFactory.getInstance();
+ Collection<LispRouter> routers = routerFactory.getRouters();
+ routers.forEach(router -> {
+ if (isInEidRecordRange(eidRecord, router.getEidRecords())) {
+ router.sendMessage(msg);
+ }
+ });
+ }
+
+ private boolean isInEidRecordRange(LispEidRecord originalRecord, List<LispEidRecord> records) {
+
+ for (LispEidRecord record : records) {
+ return LispMapUtil.isInRange(record, originalRecord) ||
+ LispMapUtil.isInRange(originalRecord, record);
+ }
+ return false;
+ }
+
+ /**
* Prevents object instantiation from external.
*/
private static final class SingletonHelper {
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispMappingDatabase.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispMappingDatabase.java
index 4cfaf12..aff24a2 100644
--- a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispMappingDatabase.java
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/LispMappingDatabase.java
@@ -17,7 +17,6 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
-import org.onlab.packet.IpPrefix;
import org.onosproject.lisp.ctl.impl.map.ExpireMap;
import org.onosproject.lisp.ctl.impl.map.ExpireHashMap;
import org.onosproject.lisp.msg.protocols.DefaultLispProxyMapRecord.DefaultMapWithProxyBuilder;
@@ -31,6 +30,7 @@
import java.util.Optional;
import static org.slf4j.LoggerFactory.getLogger;
+import static org.onosproject.lisp.ctl.impl.util.LispMapUtil.isInRange;
/**
* A singleton class that stores EID-RLOC mapping information.
@@ -165,35 +165,6 @@
}
/**
- * Generates CIDR style string from EID record.
- *
- * @param eidRecord EID record
- * @return CIDR style string
- */
- private String cidrfy(LispEidRecord eidRecord) {
- StringBuilder sb = new StringBuilder();
- sb.append(eidRecord.getPrefix().toString());
- sb.append("/");
- sb.append(eidRecord.getMaskLength());
- return sb.toString();
- }
-
- /**
- * Checks whether the EID record is included in the given EID record.
- *
- * @param origin the EID record to be compared
- * @param compare the EID record to compare
- * @return boolean result
- */
- private boolean isInRange(LispEidRecord origin, LispEidRecord compare) {
-
- IpPrefix originIpPrefix = IpPrefix.valueOf(cidrfy(origin));
- IpPrefix compareIpPrefix = IpPrefix.valueOf(cidrfy(compare));
-
- return originIpPrefix.contains(compareIpPrefix);
- }
-
- /**
* Prevents object instantiation from external.
*/
private static final class SingletonHelper {
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/util/LispMapUtil.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/util/LispMapUtil.java
new file mode 100644
index 0000000..34b6ff9
--- /dev/null
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/util/LispMapUtil.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.lisp.ctl.impl.util;
+
+import org.onlab.packet.IpPrefix;
+import org.onosproject.lisp.msg.protocols.LispEidRecord;
+
+/**
+ * A LISP map utility class includes various useful methods.
+ */
+public final class LispMapUtil {
+
+ /**
+ * Prevents object instantiation from external.
+ */
+ private LispMapUtil() {
+ }
+
+ /**
+ * Generates CIDR style string from EID record.
+ *
+ * @param eidRecord EID record
+ * @return CIDR style string
+ */
+ public static String cidrfy(LispEidRecord eidRecord) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(eidRecord.getPrefix().toString());
+ sb.append("/");
+ sb.append(eidRecord.getMaskLength());
+ return sb.toString();
+ }
+
+ /**
+ * Checks whether the EID record is included in the given EID record.
+ *
+ * @param origin the EID record to be compared
+ * @param compare the EID record to compare
+ * @return boolean result
+ */
+ public static boolean isInRange(LispEidRecord origin, LispEidRecord compare) {
+
+ IpPrefix originIpPrefix = IpPrefix.valueOf(cidrfy(origin));
+ IpPrefix compareIpPrefix = IpPrefix.valueOf(cidrfy(compare));
+
+ return originIpPrefix.contains(compareIpPrefix);
+ }
+}
\ No newline at end of file
diff --git a/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/util/package-info.java b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/util/package-info.java
new file mode 100644
index 0000000..0957591
--- /dev/null
+++ b/protocols/lisp/ctl/src/main/java/org/onosproject/lisp/ctl/impl/util/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * LISP map utility package.
+ */
+package org.onosproject.lisp.ctl.impl.util;
\ No newline at end of file