Moved ProxyArp, SDN-IP and BgpRouter to use new config format.
The new config format is based on the new network configuration subsystem.
Includes a few config fixes to NetworkConfigLoader and InterfaceManager.
Change-Id: Id7f766736decb7afb6b63c2731d3baba9fc7c764
diff --git a/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java b/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java
index e66c81b..810ca6c 100644
--- a/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java
+++ b/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java
@@ -23,6 +23,7 @@
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
@@ -49,11 +50,11 @@
// FIXME: Add mutual exclusion to make sure this happens only once per startup.
- private Map<InnerConfigPosition, ObjectNode> jsons = Maps.newHashMap();
+ private final Map<InnerConfigPosition, ObjectNode> jsons = Maps.newConcurrentMap();
private final NetworkConfigListener configListener = new InnerConfigListener();
- ObjectNode root;
+ private ObjectNode root;
@Activate
public void activate() {
@@ -101,24 +102,24 @@
* Inner class that allows for tracking of JSON class configurations.
*/
private final class InnerConfigPosition {
- private String subjectKey, subject, classKey;
+ private final String subjectKey, subject, configKey;
- private String getSubjectKey() {
+ private String subjectKey() {
return subjectKey;
}
- private String getSubject() {
+ private String subject() {
return subject;
}
- private String getClassKey() {
- return classKey;
+ private String configKey() {
+ return configKey;
}
- private InnerConfigPosition(String subjectKey, String subject, String classKey) {
+ private InnerConfigPosition(String subjectKey, String subject, String configKey) {
this.subjectKey = subjectKey;
this.subject = subject;
- this.classKey = classKey;
+ this.configKey = configKey;
}
@Override
@@ -128,15 +129,16 @@
}
if (obj instanceof InnerConfigPosition) {
final InnerConfigPosition that = (InnerConfigPosition) obj;
- return Objects.equals(this.subjectKey, that.subjectKey) && Objects.equals(this.subject, that.subject)
- && Objects.equals(this.classKey, that.classKey);
+ return Objects.equals(this.subjectKey, that.subjectKey)
+ && Objects.equals(this.subject, that.subject)
+ && Objects.equals(this.configKey, that.configKey);
}
return false;
}
@Override
public int hashCode() {
- return Objects.hash(subjectKey, subject, classKey);
+ return Objects.hash(subjectKey, subject, configKey);
}
}
@@ -174,38 +176,41 @@
}
/**
- * Apply the configurations associated with all of the config classes that are imported and have not yet been
- * applied.
+ * Apply the configurations associated with all of the config classes that
+ * are imported and have not yet been applied.
*/
- protected void applyConfigurations() {
+ private void applyConfigurations() {
Iterator<Map.Entry<InnerConfigPosition, ObjectNode>> iter = jsons.entrySet().iterator();
Map.Entry<InnerConfigPosition, ObjectNode> entry;
InnerConfigPosition key;
ObjectNode node;
String subjectKey;
- String subject;
- String classKey;
+ String subjectString;
+ String configKey;
while (iter.hasNext()) {
entry = iter.next();
node = entry.getValue();
key = entry.getKey();
- subjectKey = key.getSubjectKey();
- subject = key.getSubject();
- classKey = key.getClassKey();
+ subjectKey = key.subjectKey();
+ subjectString = key.subject();
+ configKey = key.configKey();
+
+ Class<? extends Config> configClass =
+ networkConfigService.getConfigClass(subjectKey, configKey);
//Check that the config class has been imported
- if (networkConfigService.getConfigClass(subjectKey, subject) != null) {
+ if (configClass != null) {
+
+ Object subject = networkConfigService.getSubjectFactory(subjectKey).
+ createSubject(subjectString);
//Apply the configuration
- networkConfigService.applyConfig(networkConfigService.getSubjectFactory(subjectKey).
- createSubject(subject),
- networkConfigService.getConfigClass(subjectKey, classKey), node);
+ networkConfigService.applyConfig(subject, configClass, node);
//Now that it has been applied the corresponding JSON entry is no longer needed
- jsons.remove(key);
+ iter.remove();
}
-
}
}
diff --git a/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java b/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java
index fe369ae..99d401a 100644
--- a/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java
+++ b/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java
@@ -24,6 +24,7 @@
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.net.provider.AbstractListenerProviderRegistry;
import org.onosproject.core.Permission;
import org.onosproject.net.config.NetworkConfigEvent;
@@ -86,6 +87,9 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigService networkConfigService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected InterfaceService interfaceService;
+
private HostMonitor monitor;
@Activate
@@ -93,7 +97,7 @@
store.setDelegate(delegate);
eventDispatcher.addSink(HostEvent.class, listenerRegistry);
networkConfigService.addListener(networkConfigListener);
- monitor = new HostMonitor(deviceService, packetService, this);
+ monitor = new HostMonitor(packetService, this, interfaceService);
monitor.start();
log.info("Started");
}
diff --git a/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java b/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
index 6dc71fc..fe25236 100644
--- a/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
+++ b/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
@@ -20,26 +20,23 @@
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ICMP6;
-import org.onlab.packet.IpAddress;
import org.onlab.packet.IPv6;
+import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.packet.ndp.NeighborDiscoveryOptions;
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onlab.util.Timer;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
-import org.onosproject.net.Port;
-import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.host.PortAddresses;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketService;
@@ -63,9 +60,9 @@
* </p>
*/
public class HostMonitor implements TimerTask {
- private DeviceService deviceService;
private PacketService packetService;
private HostManager hostManager;
+ private InterfaceService interfaceService;
private final Set<IpAddress> monitoredAddresses;
@@ -80,20 +77,19 @@
/**
* Creates a new host monitor.
*
- * @param deviceService device service used to find edge ports
* @param packetService packet service used to send packets on the data plane
* @param hostManager host manager used to look up host information and
* probe existing hosts
+ * @param interfaceService interface service for interface information
*/
- public HostMonitor(DeviceService deviceService, PacketService packetService,
- HostManager hostManager) {
+ public HostMonitor(PacketService packetService, HostManager hostManager,
+ InterfaceService interfaceService) {
- this.deviceService = deviceService;
this.packetService = packetService;
this.hostManager = hostManager;
+ this.interfaceService = interfaceService;
- monitoredAddresses = Collections.newSetFromMap(
- new ConcurrentHashMap<IpAddress, Boolean>());
+ monitoredAddresses = Collections.newSetFromMap(new ConcurrentHashMap<>());
hostProviders = new ConcurrentHashMap<>();
}
@@ -176,29 +172,21 @@
* @param targetIp IP address to send the request for
*/
private void sendArpNdpRequest(IpAddress targetIp) {
- // Find ports with an IP address in the target's subnet and sent ARP/ND
- // probes out those ports.
- for (Device device : deviceService.getDevices()) {
- for (Port port : deviceService.getPorts(device.id())) {
- ConnectPoint cp = new ConnectPoint(device.id(), port.number());
- Set<PortAddresses> portAddressSet =
- hostManager.getAddressBindingsForPort(cp);
+ Interface intf = interfaceService.getMatchingInterface(targetIp);
- for (PortAddresses portAddresses : portAddressSet) {
- for (InterfaceIpAddress ia : portAddresses.ipAddresses()) {
- if (ia.subnetAddress().contains(targetIp)) {
- sendArpNdpProbe(device.id(), port, targetIp,
- ia.ipAddress(),
- portAddresses.mac(),
- portAddresses.vlan());
- }
- }
- }
+ if (intf == null) {
+ return;
+ }
+
+ for (InterfaceIpAddress ia : intf.ipAddresses()) {
+ if (ia.subnetAddress().contains(targetIp)) {
+ sendArpNdpProbe(intf.connectPoint(), targetIp, ia.ipAddress(),
+ intf.mac(), intf.vlan());
}
}
}
- private void sendArpNdpProbe(DeviceId deviceId, Port port,
+ private void sendArpNdpProbe(ConnectPoint connectPoint,
IpAddress targetIp,
IpAddress sourceIp, MacAddress sourceMac,
VlanId vlan) {
@@ -215,14 +203,14 @@
}
List<Instruction> instructions = new ArrayList<>();
- instructions.add(Instructions.createOutput(port.number()));
+ instructions.add(Instructions.createOutput(connectPoint.port()));
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(port.number())
+ .setOutput(connectPoint.port())
.build();
OutboundPacket outboundPacket =
- new DefaultOutboundPacket(deviceId, treatment,
+ new DefaultOutboundPacket(connectPoint.deviceId(), treatment,
ByteBuffer.wrap(probePacket.serialize()));
packetService.emit(outboundPacket);
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
index 8fad769..06d0e9a 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
@@ -98,7 +98,7 @@
partialTree = true;
for (Link link : path.links()) {
- if (links.containsKey(link.src().deviceId())) {
+ if (links.containsKey(link.dst().deviceId())) {
// We've already reached the existing tree with the first
// part of this path. Add the merging point with different
// incoming port, but don't add the remainder of the path
diff --git a/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java b/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java
index b5acde6..1a56d0e 100644
--- a/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java
+++ b/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java
@@ -34,6 +34,8 @@
import org.onlab.packet.ndp.NeighborDiscoveryOptions;
import org.onlab.packet.ndp.NeighborSolicitation;
import org.onosproject.core.Permission;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.device.DeviceService;
@@ -41,8 +43,6 @@
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.host.PortAddresses;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
@@ -53,9 +53,7 @@
import org.slf4j.Logger;
import java.nio.ByteBuffer;
-import java.util.HashSet;
import java.util.Set;
-import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -95,17 +93,15 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ProxyArpStore store;
- /**
- * Listens to both device service and link service to determine
- * whether a port is internal or external.
- */
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected InterfaceService interfaceService;
+
@Activate
public void activate() {
store.setDelegate(this::sendTo);
log.info("Started");
}
-
@Deactivate
public void deactivate() {
store.setDelegate(null);
@@ -140,21 +136,18 @@
VlanId vlan = vlanId(eth.getVlanID());
- if (isOutsidePort(inPort)) {
+ if (hasIpAddress(inPort)) {
// If the request came from outside the network, only reply if it was
// for one of our external addresses.
- Set<PortAddresses> addressSet =
- hostService.getAddressBindingsForPort(inPort);
- for (PortAddresses addresses : addressSet) {
- for (InterfaceIpAddress ia : addresses.ipAddresses()) {
- if (ia.ipAddress().equals(targetAddress)) {
- Ethernet arpReply =
- ARP.buildArpReply(targetAddress, addresses.mac(), eth);
- sendTo(arpReply, inPort);
- }
- }
- }
+ interfaceService.getInterfacesByPort(inPort)
+ .stream()
+ .filter(intf -> intf.ipAddresses()
+ .stream()
+ .anyMatch(ia -> ia.ipAddress().equals(targetAddress)))
+ .forEach(intf -> buildAndSendArp(targetAddress, intf.mac(), eth, inPort));
+
+ // Stop here and don't proxy ARPs if the port has an IP address
return;
}
@@ -164,7 +157,7 @@
Host dst = null;
Host src = hostService.getHost(hostId(eth.getSourceMAC(),
- vlanId(eth.getVlanID())));
+ vlanId(eth.getVlanID())));
for (Host host : hosts) {
if (host.vlan().equals(vlan)) {
@@ -175,8 +168,7 @@
if (src != null && dst != null) {
// We know the target host so we can respond
- Ethernet arpReply = ARP.buildArpReply(targetAddress, dst.mac(), eth);
- sendTo(arpReply, inPort);
+ buildAndSendArp(targetAddress, dst.mac(), eth, inPort);
return;
}
@@ -185,16 +177,14 @@
// address. Forward it over to the correct port.
Ip4Address source =
Ip4Address.valueOf(arp.getSenderProtocolAddress());
- Set<PortAddresses> sourceAddresses = findPortsInSubnet(source);
+
boolean matched = false;
- for (PortAddresses pa : sourceAddresses) {
- for (InterfaceIpAddress ia : pa.ipAddresses()) {
- if (ia.ipAddress().equals(source) &&
- pa.vlan().equals(vlan)) {
- matched = true;
- sendTo(eth, pa.connectPoint());
- break;
- }
+ Set<Interface> interfaces = interfaceService.getInterfacesByIp(source);
+ for (Interface intf : interfaces) {
+ if (intf.vlan().equals(vlan)) {
+ matched = true;
+ sendTo(eth, intf.connectPoint());
+ break;
}
}
@@ -202,10 +192,8 @@
return;
}
- //
// The request couldn't be resolved.
// Flood the request on all ports except the incoming port.
- //
flood(eth, inPort);
}
@@ -219,42 +207,14 @@
// If the request came from outside the network, only reply if it was
// for one of our external addresses.
- if (isOutsidePort(inPort)) {
- Set<PortAddresses> addressSet =
- hostService.getAddressBindingsForPort(inPort);
-
- for (PortAddresses addresses : addressSet) {
- for (InterfaceIpAddress ia : addresses.ipAddresses()) {
- if (ia.ipAddress().equals(targetAddress)) {
- Ethernet ndpReply =
- buildNdpReply(targetAddress, addresses.mac(), eth);
- sendTo(ndpReply, inPort);
- }
- }
- }
+ if (hasIpAddress(inPort)) {
+ interfaceService.getInterfacesByPort(inPort)
+ .stream()
+ .filter(intf -> intf.ipAddresses()
+ .stream()
+ .anyMatch(ia -> ia.ipAddress().equals(targetAddress)))
+ .forEach(intf -> buildAndSendNdp(targetAddress, intf.mac(), eth, inPort));
return;
- } else {
- // If the source address matches one of our external addresses
- // it could be a request from an internal host to an external
- // address. Forward it over to the correct ports.
- Ip6Address source =
- Ip6Address.valueOf(ipv6.getSourceAddress());
- Set<PortAddresses> sourceAddresses = findPortsInSubnet(source);
- boolean matched = false;
- for (PortAddresses pa : sourceAddresses) {
- for (InterfaceIpAddress ia : pa.ipAddresses()) {
- if (ia.ipAddress().equals(source) &&
- pa.vlan().equals(vlan)) {
- matched = true;
- sendTo(eth, pa.connectPoint());
- break;
- }
- }
- }
-
- if (matched) {
- return;
- }
}
// Continue with normal proxy ARP case
@@ -272,23 +232,49 @@
}
}
- if (src == null || dst == null) {
- //
- // The request couldn't be resolved.
- // Flood the request on all ports except the incoming ports.
- //
- flood(eth, inPort);
+ if (src != null || dst != null) {
+ // We know the target host so we can respond
+ buildAndSendNdp(targetAddress, dst.mac(), eth, inPort);
return;
}
- //
- // Reply on the port the request was received on
- //
- Ethernet ndpReply = buildNdpReply(targetAddress, dst.mac(), eth);
- sendTo(ndpReply, inPort);
+ // If the source address matches one of our external addresses
+ // it could be a request from an internal host to an external
+ // address. Forward it over to the correct port.
+ Ip6Address source =
+ Ip6Address.valueOf(ipv6.getSourceAddress());
+
+ boolean matched = false;
+
+ Set<Interface> interfaces = interfaceService.getInterfacesByIp(source);
+ for (Interface intf : interfaces) {
+ if (intf.vlan().equals(vlan)) {
+ matched = true;
+ sendTo(eth, intf.connectPoint());
+ break;
+ }
+ }
+
+ if (matched) {
+ return;
+ }
+
+ // The request couldn't be resolved.
+ // Flood the request on all ports except the incoming ports.
+ flood(eth, inPort);
}
//TODO checkpoint
+ private void buildAndSendArp(Ip4Address srcIp, MacAddress srcMac,
+ Ethernet request, ConnectPoint port) {
+ sendTo(ARP.buildArpReply(srcIp, srcMac, request), port);
+ }
+
+ private void buildAndSendNdp(Ip6Address srcIp, MacAddress srcMac,
+ Ethernet request, ConnectPoint port) {
+ sendTo(buildNdpReply(srcIp, srcMac, request), port);
+ }
+
/**
* Outputs the given packet out the given port.
*
@@ -314,30 +300,18 @@
}
/**
- * Finds ports with an address in the subnet of the target address.
- *
- * @param target the target address to find a matching port for
- * @return a set of PortAddresses describing ports in the subnet
- */
- private Set<PortAddresses> findPortsInSubnet(IpAddress target) {
- Set<PortAddresses> result = new HashSet<>();
- for (PortAddresses addresses : hostService.getAddressBindings()) {
- result.addAll(addresses.ipAddresses().stream().filter(ia -> ia.subnetAddress().contains(target)).
- map(ia -> addresses).collect(Collectors.toList()));
- }
- return result;
- }
-
- /**
- * Returns whether the given port is an outside-facing port with an IP
- * address configured.
+ * Returns whether the given port has any IP addresses configured or not.
*
* @param port the port to check
- * @return true if the port is an outside-facing port, otherwise false
+ * @return true if the port has at least one IP address configured,
+ * otherwise false
*/
- private boolean isOutsidePort(ConnectPoint port) {
- // TODO: Is this sufficient to identify outside-facing ports: just having IP addresses on a port?
- return !hostService.getAddressBindingsForPort(port).isEmpty();
+ private boolean hasIpAddress(ConnectPoint port) {
+ return interfaceService.getInterfacesByPort(port)
+ .stream()
+ .map(intf -> intf.ipAddresses())
+ .findAny()
+ .isPresent();
}
@Override
@@ -418,7 +392,7 @@
ByteBuffer buf = ByteBuffer.wrap(request.serialize());
for (ConnectPoint connectPoint : edgeService.getEdgePoints()) {
- if (isOutsidePort(connectPoint) || connectPoint.equals(inPort)) {
+ if (hasIpAddress(connectPoint) || connectPoint.equals(inPort)) {
continue;
}
@@ -427,7 +401,6 @@
packetService.emit(new DefaultOutboundPacket(connectPoint.deviceId(),
builder.build(), buf));
}
-
}
/**