Use component config for the default private gateway MAC
Change-Id: Ie0d17d6c78f4c13093a7b7ec6032f9f6e3e7c3e6
diff --git a/src/main/java/org/opencord/cordvtn/api/Constants.java b/src/main/java/org/opencord/cordvtn/api/Constants.java
index d6d2831..6730cf3 100644
--- a/src/main/java/org/opencord/cordvtn/api/Constants.java
+++ b/src/main/java/org/opencord/cordvtn/api/Constants.java
@@ -15,8 +15,6 @@
*/
package org.opencord.cordvtn.api;
-import org.onlab.packet.Ip4Address;
-
/**
* Provides constants used in CORD VTN services.
*/
@@ -37,6 +35,5 @@
public static final String DEFAULT_OF_PROTOCOL = "tcp";
public static final int DEFAULT_OF_PORT = 6653;
public static final int DEFAULT_OVSDB_PORT = 6640;
- public static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
- public static final int DHCP_INFINITE_LEASE = -1;
+ public static final String DEFAULT_GATEWAY_MAC_STR = "00:00:00:00:00:01";
}
diff --git a/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java b/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java
index aa90093..bb4ce5e 100644
--- a/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java
+++ b/src/main/java/org/opencord/cordvtn/api/CordVtnConfig.java
@@ -54,6 +54,7 @@
protected final Logger log = getLogger(getClass());
+ @Deprecated
private static final String PRIVATE_GATEWAY_MAC = "privateGatewayMac";
private static final String PUBLIC_GATEWAYS = "publicGateways";
private static final String GATEWAY_IP = "gatewayIp";
@@ -106,7 +107,6 @@
}
// check all mandatory fields are present and valid
- result = result && isMacAddress(PRIVATE_GATEWAY_MAC, MANDATORY);
result = result && isIpPrefix(LOCAL_MANAGEMENT_IP, MANDATORY);
for (JsonNode node : object.get(CORDVTN_NODES)) {
@@ -242,16 +242,6 @@
}
/**
- * Returns private network gateway MAC address.
- *
- * @return mac address
- */
- public MacAddress privateGatewayMac() {
- JsonNode jsonNode = object.get(PRIVATE_GATEWAY_MAC);
- return MacAddress.valueOf(jsonNode.asText());
- }
-
- /**
* Returns public network gateway IP and MAC address pairs.
*
* @return map of ip and mac address
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtnArpProxy.java b/src/main/java/org/opencord/cordvtn/impl/CordVtnArpProxy.java
index e8b4775..4dc69a2 100644
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtnArpProxy.java
+++ b/src/main/java/org/opencord/cordvtn/impl/CordVtnArpProxy.java
@@ -15,10 +15,13 @@
*/
package org.opencord.cordvtn.impl;
+import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.ARP;
@@ -27,6 +30,8 @@
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
+import org.onlab.util.Tools;
+import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
@@ -52,15 +57,18 @@
import org.opencord.cordvtn.api.core.ServiceNetworkListener;
import org.opencord.cordvtn.api.core.ServiceNetworkService;
import org.opencord.cordvtn.api.net.ServiceNetwork;
+import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import java.nio.ByteBuffer;
+import java.util.Dictionary;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.opencord.cordvtn.api.Constants.DEFAULT_GATEWAY_MAC_STR;
import static org.opencord.cordvtn.api.net.ServiceNetwork.NetworkType.*;
import static org.slf4j.LoggerFactory.getLogger;
@@ -71,6 +79,8 @@
public class CordVtnArpProxy {
protected final Logger log = getLogger(getClass());
+ private static final String PRIVATE_GATEWAY_MAC = "privateGatewayMac";
+
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
@@ -81,7 +91,10 @@
protected HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected NetworkConfigService configService;
+ protected NetworkConfigService netConfigService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ComponentConfigService compConfigService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CordVtnNodeManager nodeManager;
@@ -89,10 +102,14 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ServiceNetworkService snetService;
+ @Property(name = PRIVATE_GATEWAY_MAC, value = DEFAULT_GATEWAY_MAC_STR,
+ label = "Fake MAC address for virtual network gateway")
+ private String privateGatewayMacStr = DEFAULT_GATEWAY_MAC_STR;
+ private MacAddress privateGatewayMac = MacAddress.valueOf(privateGatewayMacStr);
+
private final PacketProcessor packetProcessor = new InternalPacketProcessor();
private final Map<IpAddress, MacAddress> gateways = Maps.newConcurrentMap();
- private MacAddress privateGatewayMac = MacAddress.NONE;
private NetworkConfigListener configListener = new InternalConfigListener();
private ServiceNetworkListener snetListener = new InternalServiceNetworkListener();
private ApplicationId appId;
@@ -100,24 +117,42 @@
@Activate
protected void activate() {
appId = coreService.registerApplication(Constants.CORDVTN_APP_ID);
- configService.addListener(configListener);
- readConfiguration();
+ compConfigService.registerProperties(getClass());
+
+ netConfigService.addListener(configListener);
+ readPublicGateways();
+ snetService.addListener(snetListener);
+ readPrivateGateways();
packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
requestPacket();
- snetService.addListener(snetListener);
- snetService.serviceNetworks().stream()
- .filter(net -> net.type() == PRIVATE || net.type() == VSG)
- .filter(net -> net.serviceIp() != null)
- .forEach(net -> addGateway(net.serviceIp(), privateGatewayMac));
+ log.info("Started");
}
@Deactivate
protected void deactivate() {
- snetService.removeListener(snetListener);
packetService.removeProcessor(packetProcessor);
- configService.removeListener(configListener);
+ snetService.removeListener(snetListener);
+ netConfigService.removeListener(configListener);
+ compConfigService.unregisterProperties(getClass(), false);
+
+ log.info("Stopped");
+ }
+
+ @Modified
+ protected void modified(ComponentContext context) {
+ Dictionary<?, ?> properties = context.getProperties();
+ String updatedMac;
+
+ updatedMac = Tools.get(properties, PRIVATE_GATEWAY_MAC);
+ if (!Strings.isNullOrEmpty(updatedMac) &&
+ !updatedMac.equals(privateGatewayMacStr)) {
+ privateGatewayMacStr = updatedMac;
+ privateGatewayMac = MacAddress.valueOf(privateGatewayMacStr);
+ }
+
+ log.info("Modified");
}
/**
@@ -150,6 +185,13 @@
Optional.empty());
}
+ private void readPrivateGateways() {
+ snetService.serviceNetworks().stream()
+ .filter(net -> net.type() == PRIVATE || net.type() == VSG)
+ .filter(net -> net.serviceIp() != null)
+ .forEach(net -> addGateway(net.serviceIp(), privateGatewayMac));
+ }
+
/**
* Adds a given gateway IP and MAC address to this ARP proxy.
*
@@ -157,9 +199,9 @@
* @param gatewayMac gateway mac address
*/
private void addGateway(IpAddress gatewayIp, MacAddress gatewayMac) {
- checkNotNull(gatewayIp);
+ checkNotNull(gatewayIp, "Gateway IP address cannot be null");
checkArgument(gatewayMac != null && gatewayMac != MacAddress.NONE,
- "privateGatewayMac is not configured");
+ "Gateway MAC address cannot be null or NONE");
MacAddress existing = gateways.get(gatewayIp);
if (existing != null && !existing.equals(privateGatewayMac) &&
@@ -300,7 +342,7 @@
}
Ethernet ethArp = buildGratuitousArp(gatewayIp.getIp4Address(), gatewayMac);
- instances.stream().forEach(instance -> {
+ instances.forEach(instance -> {
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setOutput(instance.portNumber())
.build();
@@ -420,17 +462,14 @@
}
}
- private void readConfiguration() {
- CordVtnConfig config = configService.getConfig(appId, CordVtnConfig.class);
+ private void readPublicGateways() {
+ CordVtnConfig config = netConfigService.getConfig(appId, CordVtnConfig.class);
if (config == null) {
log.debug("No configuration found");
return;
}
- // TODO handle the case that private gateway MAC is changed
- privateGatewayMac = config.privateGatewayMac();
- log.debug("Set default service IP MAC address {}", privateGatewayMac);
- config.publicGateways().entrySet().stream().forEach(entry -> {
+ config.publicGateways().entrySet().forEach(entry -> {
addGateway(entry.getKey(), entry.getValue());
});
// TODO send gratuitous arp in case the MAC is changed
@@ -449,7 +488,7 @@
switch (event.type()) {
case CONFIG_ADDED:
case CONFIG_UPDATED:
- readConfiguration();
+ readPublicGateways();
break;
default:
break;
diff --git a/src/main/java/org/opencord/cordvtn/impl/CordVtnDhcpProxy.java b/src/main/java/org/opencord/cordvtn/impl/CordVtnDhcpProxy.java
index d78be9b..efb882b 100644
--- a/src/main/java/org/opencord/cordvtn/impl/CordVtnDhcpProxy.java
+++ b/src/main/java/org/opencord/cordvtn/impl/CordVtnDhcpProxy.java
@@ -15,11 +15,14 @@
*/
package org.opencord.cordvtn.impl;
+import com.google.common.base.Strings;
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;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.DHCP;
@@ -32,14 +35,13 @@
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onlab.packet.UDP;
+import org.onlab.util.Tools;
+import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
-import org.onosproject.net.config.NetworkConfigEvent;
-import org.onosproject.net.config.NetworkConfigListener;
-import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
@@ -51,24 +53,25 @@
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.opencord.cordvtn.api.Constants;
-import org.opencord.cordvtn.api.CordVtnConfig;
import org.opencord.cordvtn.api.core.Instance;
import org.opencord.cordvtn.api.core.ServiceNetworkService;
import org.opencord.cordvtn.api.net.NetworkId;
import org.opencord.cordvtn.api.net.ServiceNetwork;
+import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import java.nio.ByteBuffer;
import java.util.Arrays;
+import java.util.Dictionary;
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.*;
import static org.onlab.packet.DHCPPacketType.DHCPACK;
import static org.onlab.packet.DHCPPacketType.DHCPOFFER;
+import static org.opencord.cordvtn.api.Constants.DEFAULT_GATEWAY_MAC_STR;
import static org.opencord.cordvtn.api.net.ServiceNetwork.DependencyType.BIDIRECTIONAL;
import static org.opencord.cordvtn.api.net.ServiceNetwork.NetworkType.MANAGEMENT_HOST;
import static org.opencord.cordvtn.api.net.ServiceNetwork.NetworkType.MANAGEMENT_LOCAL;
@@ -82,11 +85,13 @@
protected final Logger log = getLogger(getClass());
- private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
- private static final byte PACKET_TTL = (byte) 127;
- // TODO add MTU, static route option codes to ONOS DHCP and remove here
+ private static final String DHCP_SERVER_MAC = "dhcpServerMac";
+
private static final byte DHCP_OPTION_MTU = (byte) 26;
private static final byte DHCP_OPTION_CLASSLESS_STATIC_ROUTE = (byte) 121;
+
+ private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
+ private static final byte DEFAULT_PACKET_TTL = (byte) 127;
private static final byte[] DHCP_DATA_LEASE_INFINITE =
ByteBuffer.allocate(4).putInt(-1).array();
private static final byte[] DHCP_DATA_MTU_DEFAULT =
@@ -96,7 +101,7 @@
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected NetworkConfigService configService;
+ protected ComponentConfigService configService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
@@ -107,31 +112,46 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ServiceNetworkService snetService;
+ @Property(name = DHCP_SERVER_MAC, value = DEFAULT_GATEWAY_MAC_STR,
+ label = "Fake MAC address for DHCP server interface")
+ private String dhcpServerMac = DEFAULT_GATEWAY_MAC_STR;
+
private final PacketProcessor packetProcessor = new InternalPacketProcessor();
- private final NetworkConfigListener configListener = new InternalConfigListener();
private ApplicationId appId;
- private MacAddress dhcpServerMac = MacAddress.NONE;
@Activate
protected void activate() {
appId = coreService.registerApplication(Constants.CORDVTN_APP_ID);
- configService.addListener(configListener);
- readConfiguration();
-
+ configService.registerProperties(getClass());
packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
requestPackets();
+
log.info("Started");
}
@Deactivate
protected void deactivate() {
- configService.removeListener(configListener);
packetService.removeProcessor(packetProcessor);
+ configService.unregisterProperties(getClass(), false);
cancelPackets();
+
log.info("Stopped");
}
+ @Modified
+ protected void modified(ComponentContext context) {
+ Dictionary<?, ?> properties = context.getProperties();
+ String updatedMac;
+
+ updatedMac = Tools.get(properties, DHCP_SERVER_MAC);
+ if (!Strings.isNullOrEmpty(updatedMac) && !updatedMac.equals(dhcpServerMac)) {
+ dhcpServerMac = updatedMac;
+ }
+
+ log.info("Modified");
+ }
+
private void requestPackets() {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
@@ -245,9 +265,6 @@
private Ethernet buildReply(Ethernet ethRequest, byte packetType,
Instance reqInstance) {
- checkArgument(!dhcpServerMac.equals(MacAddress.NONE),
- "DHCP server MAC is not set");
-
ServiceNetwork snet = snetService.serviceNetwork(reqInstance.netId());
Ip4Address serverIp = snet.serviceIp().getIp4Address();
@@ -260,7 +277,7 @@
IPv4 ipv4Reply = new IPv4();
ipv4Reply.setSourceAddress(serverIp.toInt());
ipv4Reply.setDestinationAddress(reqInstance.ipAddress().toInt());
- ipv4Reply.setTtl(PACKET_TTL);
+ ipv4Reply.setTtl(DEFAULT_PACKET_TTL);
UDP udpRequest = (UDP) ipv4Request.getPayload();
UDP udpReply = new UDP();
@@ -402,7 +419,7 @@
.filter(Objects::nonNull)
.collect(Collectors.toSet());
- providers.stream().forEach(provider -> {
+ providers.forEach(provider -> {
result.add((byte) provider.subnet().prefixLength());
result.addAll(getSignificantOctets(provider.subnet()));
result.addAll(router);
@@ -413,7 +430,7 @@
.filter(net -> isBidirectionalProvider(net, snet.id()))
.collect(Collectors.toSet());
- subscribers.stream().forEach(subscriber -> {
+ subscribers.forEach(subscriber -> {
result.add((byte) subscriber.subnet().prefixLength());
result.addAll(getSignificantOctets(subscriber.subnet()));
result.addAll(router);
@@ -425,8 +442,7 @@
private boolean isBidirectionalProvider(ServiceNetwork snet, NetworkId targetNetId) {
return snet.providers().entrySet().stream()
.filter(p -> Objects.equals(p.getKey(), targetNetId))
- .filter(p -> p.getValue() == BIDIRECTIONAL)
- .findAny().isPresent();
+ .anyMatch(p -> p.getValue() == BIDIRECTIONAL);
}
private List<Byte> getSignificantOctets(IpPrefix ipPrefix) {
@@ -438,35 +454,4 @@
return Bytes.asList(result);
}
}
-
- private void readConfiguration() {
- CordVtnConfig config = configService.getConfig(appId, CordVtnConfig.class);
- if (config == null) {
- log.debug("No configuration found");
- return;
- }
- dhcpServerMac = config.privateGatewayMac();
- log.debug("Set default DHCP server MAC address {}", dhcpServerMac);
- }
-
- private class InternalConfigListener implements NetworkConfigListener {
-
- @Override
- public boolean isRelevant(NetworkConfigEvent event) {
- return event.configClass().equals(CordVtnConfig.class);
- }
-
- @Override
- public void event(NetworkConfigEvent event) {
-
- switch (event.type()) {
- case CONFIG_ADDED:
- case CONFIG_UPDATED:
- readConfiguration();
- break;
- default:
- break;
- }
- }
- }
}