CORD-592 Added DHCP classless static route option for service dependency
And moved config registration code to cordvtnmanager
Change-Id: I2657ca21659fa1abfb81799a922524ca9c52ead6
diff --git a/src/main/java/org/opencord/cordvtn/api/net/ServiceNetwork.java b/src/main/java/org/opencord/cordvtn/api/net/ServiceNetwork.java
index cbdde5f..6b26daf 100644
--- a/src/main/java/org/opencord/cordvtn/api/net/ServiceNetwork.java
+++ b/src/main/java/org/opencord/cordvtn/api/net/ServiceNetwork.java
@@ -22,6 +22,7 @@
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.opencord.cordvtn.api.dependency.Dependency.Type.BIDIRECTIONAL;
/**
* Representation of a service network which holds service specific information,
@@ -91,6 +92,19 @@
.findAny().isPresent();
}
+ /**
+ * Returns if the given network is the provider of this network with
+ * bidirectional access type.
+ *
+ * @param netId network id
+ * @return true if the given network is a bidrectional provider
+ */
+ public boolean isBidirectionalProvider(NetworkId netId) {
+ return providers.stream().filter(p -> Objects.equals(p.id(), netId))
+ .filter(p -> p.type() == BIDIRECTIONAL)
+ .findAny().isPresent();
+ }
+
@Override
public boolean equals(Object obj) {
if (this == obj) {
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtnDhcpProxy.java b/src/main/java/org/opencord/cordvtn/impl/CordVtnDhcpProxy.java
index ba5a4af..607e3b0 100644
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtnDhcpProxy.java
+++ b/src/main/java/org/opencord/cordvtn/impl/CordVtnDhcpProxy.java
@@ -16,6 +16,7 @@
package org.opencord.cordvtn.impl;
import com.google.common.collect.Lists;
+import com.google.common.primitives.Bytes;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -27,6 +28,7 @@
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onlab.packet.UDP;
@@ -56,7 +58,11 @@
import org.slf4j.Logger;
import java.nio.ByteBuffer;
+import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkArgument;
import static org.onlab.packet.DHCP.DHCPOptionCode.*;
@@ -76,8 +82,9 @@
private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
private static final byte PACKET_TTL = (byte) 127;
- // TODO add MTU option code to ONOS DHCP implementation and remove this
+ // TODO add MTU, static route option codes to ONOS DHCP and remove here
private static final byte DHCP_OPTION_MTU = (byte) 26;
+ private static final byte DHCP_OPTION_CLASSLESS_STATIC_ROUTE = (byte) 121;
private static final byte[] DHCP_DATA_LEASE_INFINITE =
ByteBuffer.allocate(4).putInt(-1).array();
private static final byte[] DHCP_DATA_MTU_DEFAULT =
@@ -117,13 +124,12 @@
@Deactivate
protected void deactivate() {
+ configRegistry.removeListener(configListener);
packetService.removeProcessor(packetProcessor);
cancelPackets();
log.info("Stopped");
}
- // TODO implement public method forceRenew
-
private void requestPackets() {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
@@ -341,6 +347,7 @@
option.setData(broadcast.toOctets());
options.add(option);
+ // domain server
option = new DHCPOption();
option.setCode(OptionCode_DomainServer.getValue());
option.setLength((byte) 4);
@@ -363,7 +370,15 @@
options.add(option);
}
- // TODO add host route option if network has service dependency
+ // classless static routes
+ byte[] data = getClasslessStaticRoutesData(vtnNet);
+ if (data.length >= 5) {
+ option = new DHCPOption();
+ option.setCode(DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
+ option.setLength((byte) data.length);
+ option.setData(data);
+ options.add(option);
+ }
// end option
option = new DHCPOption();
@@ -374,6 +389,45 @@
dhcpReply.setOptions(options);
return dhcpReply;
}
+
+ private byte[] getClasslessStaticRoutesData(VtnNetwork vtnNet) {
+ List<Byte> result = Lists.newArrayList();
+ List<Byte> router = Bytes.asList(vtnNet.serviceIp().toOctets());
+
+ // static routes for the providers
+ Set<VtnNetwork> providers = vtnNet.providers().stream()
+ .map(provider -> cordVtnService.vtnNetwork(provider.id()))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+
+ providers.stream().forEach(provider -> {
+ result.add((byte) provider.subnet().prefixLength());
+ result.addAll(getSignificantOctets(provider.subnet()));
+ result.addAll(router);
+ });
+
+ // static routes for the bidirectional subscribers
+ Set<VtnNetwork> subscribers = cordVtnService.vtnNetworks().stream()
+ .filter(net -> net.isBidirectionalProvider(vtnNet.id()))
+ .collect(Collectors.toSet());
+
+ subscribers.stream().forEach(subscriber -> {
+ result.add((byte) subscriber.subnet().prefixLength());
+ result.addAll(getSignificantOctets(subscriber.subnet()));
+ result.addAll(router);
+ });
+
+ return Bytes.toArray(result);
+ }
+
+ private List<Byte> getSignificantOctets(IpPrefix ipPrefix) {
+ int numOfOctets = ipPrefix.prefixLength() / 8;
+ if (ipPrefix.prefixLength() % 8 != 0) {
+ numOfOctets += 1;
+ }
+ byte[] result = Arrays.copyOfRange(ipPrefix.address().toOctets(), 0, numOfOctets);
+ return Bytes.asList(result);
+ }
}
private void readConfiguration() {
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtnManager.java b/src/main/java/org/opencord/cordvtn/impl/CordVtnManager.java
index e93eaf6..f3dd1f4 100644
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtnManager.java
+++ b/src/main/java/org/opencord/cordvtn/impl/CordVtnManager.java
@@ -27,7 +27,10 @@
import org.onosproject.event.ListenerRegistry;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.host.HostService;
import org.opencord.cordvtn.api.Constants;
import org.opencord.cordvtn.api.config.CordVtnConfig;
@@ -108,6 +111,9 @@
protected NetworkConfigService configService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry configRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -116,18 +122,31 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CordVtnStore store;
+ // TODO add cordvtn config service and move this
+ private static final Class<CordVtnConfig> CONFIG_CLASS = CordVtnConfig.class;
+ private final ConfigFactory configFactory =
+ new ConfigFactory<ApplicationId, CordVtnConfig>(
+ SubjectFactories.APP_SUBJECT_FACTORY, CONFIG_CLASS, "cordvtn") {
+ @Override
+ public CordVtnConfig createConfig() {
+ return new CordVtnConfig();
+ }
+ };
+
private final CordVtnStoreDelegate delegate = new InternalCordVtnStoreDelegate();
private ApplicationId appId;
@Activate
protected void activate() {
appId = coreService.registerApplication(Constants.CORDVTN_APP_ID);
+ configRegistry.registerConfigFactory(configFactory);
store.setDelegate(delegate);
log.info("Started");
}
@Deactivate
protected void deactivate() {
+ configRegistry.unregisterConfigFactory(configFactory);
store.unsetDelegate(delegate);
log.info("Stopped");
}
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtnNodeManager.java b/src/main/java/org/opencord/cordvtn/impl/CordVtnNodeManager.java
index c2a89b9..f7f9c2d 100644
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtnNodeManager.java
+++ b/src/main/java/org/opencord/cordvtn/impl/CordVtnNodeManager.java
@@ -29,36 +29,26 @@
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.LeadershipService;
import org.onosproject.cluster.NodeId;
-import org.onosproject.net.AnnotationKeys;
-import org.onosproject.net.behaviour.BridgeDescription;
-import org.onosproject.net.behaviour.DefaultBridgeDescription;
-import org.onosproject.net.behaviour.InterfaceConfig;
-import org.onosproject.net.behaviour.TunnelEndPoints;
-import org.onosproject.net.behaviour.TunnelKeys;
-import org.onosproject.net.config.ConfigFactory;
-import org.onosproject.net.config.basics.SubjectFactories;
-import org.opencord.cordvtn.api.node.ConnectionHandler;
-import org.opencord.cordvtn.api.config.CordVtnConfig;
-import org.opencord.cordvtn.api.node.CordVtnNode;
-import org.opencord.cordvtn.api.node.CordVtnNodeState;
-import org.opencord.cordvtn.api.instance.InstanceService;
-import org.opencord.cordvtn.api.node.NetworkAddress;
-import org.opencord.cordvtn.api.node.SshAccessInfo;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
+import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.BridgeConfig;
+import org.onosproject.net.behaviour.BridgeDescription;
import org.onosproject.net.behaviour.BridgeName;
import org.onosproject.net.behaviour.ControllerInfo;
+import org.onosproject.net.behaviour.DefaultBridgeDescription;
import org.onosproject.net.behaviour.DefaultTunnelDescription;
+import org.onosproject.net.behaviour.InterfaceConfig;
import org.onosproject.net.behaviour.TunnelDescription;
+import org.onosproject.net.behaviour.TunnelEndPoints;
+import org.onosproject.net.behaviour.TunnelKeys;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
-import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.device.DeviceAdminService;
import org.onosproject.net.device.DeviceEvent;
@@ -75,6 +65,13 @@
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.Versioned;
+import org.opencord.cordvtn.api.config.CordVtnConfig;
+import org.opencord.cordvtn.api.instance.InstanceService;
+import org.opencord.cordvtn.api.node.ConnectionHandler;
+import org.opencord.cordvtn.api.node.CordVtnNode;
+import org.opencord.cordvtn.api.node.CordVtnNodeState;
+import org.opencord.cordvtn.api.node.NetworkAddress;
+import org.opencord.cordvtn.api.node.SshAccessInfo;
import org.slf4j.Logger;
import java.util.List;
@@ -118,9 +115,6 @@
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected NetworkConfigRegistry configRegistry;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigService configService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -150,16 +144,6 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CordVtnPipeline pipeline;
- private static final Class<CordVtnConfig> CONFIG_CLASS = CordVtnConfig.class;
- private final ConfigFactory configFactory =
- new ConfigFactory<ApplicationId, CordVtnConfig>(
- SubjectFactories.APP_SUBJECT_FACTORY, CONFIG_CLASS, "cordvtn") {
- @Override
- public CordVtnConfig createConfig() {
- return new CordVtnConfig();
- }
- };
-
private final ExecutorService eventExecutor =
newSingleThreadExecutor(groupedThreads("onos/cordvtn-node", "event-handler", log));
@@ -230,7 +214,6 @@
appId = coreService.registerApplication(CORDVTN_APP_ID);
leadershipService.runForLeadership(appId.name());
localNodeId = clusterService.getLocalNode().id();
- configRegistry.registerConfigFactory(configFactory);
nodeStore = storageService.<String, CordVtnNode>consistentMapBuilder()
.withSerializer(Serializer.using(NODE_SERIALIZER.build()))
@@ -254,7 +237,6 @@
nodeStore.removeListener(nodeStoreListener);
leadershipService.withdraw(appId.name());
- configRegistry.unregisterConfigFactory(configFactory);
eventExecutor.shutdown();
log.info("Stopped");
@@ -850,7 +832,7 @@
return;
}
- CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
+ CordVtnConfig config = configService.getConfig(appId, CordVtnConfig.class);
if (config == null) {
log.debug("No configuration found");
return;
@@ -859,7 +841,7 @@
}
private void readControllers() {
- CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
+ CordVtnConfig config = configService.getConfig(appId, CordVtnConfig.class);
if (config == null) {
log.debug("No configuration found");
return;