CORD-339 Network config host provider
* Implement new application org.onosproject.netcfghost
* Implement BasicHostConfig to include IP and location information
- Update network-cfg.json to add host config example
- Add network-cfg-2x2-leaf-spine.json for 2x2 leaf-spine network in SegmentRouting
* Update Segment Rounting
- Punt ARP packets
(which is done by HostLocationProvider previously)
- Check existing hosts when device connected or configured
Change-Id: I03986ddc8203d740b5bf26903e3dbf866d4d4600
diff --git a/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index 9922587..e645165 100644
--- a/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -513,6 +513,7 @@
public void populatePortAddressingRules(DeviceId deviceId) {
rulePopulator.populateRouterMacVlanFilters(deviceId);
rulePopulator.populateRouterIpPunts(deviceId);
+ rulePopulator.populateArpPunts(deviceId);
}
/**
diff --git a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index a07a15d..fc6a3f3 100644
--- a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -511,6 +511,39 @@
}
/**
+ * Creates a forwarding objective to punt all IP packets, destined to the
+ * router's port IP addresses, to the controller. Note that the input
+ * port should not be matched on, as these packets can come from any input.
+ * Furthermore, these are applied only by the master instance.
+ *
+ * @param deviceId the switch dpid for the router
+ */
+ public void populateArpPunts(DeviceId deviceId) {
+ if (!srManager.mastershipService.isLocalMaster(deviceId)) {
+ log.debug("Not installing port-IP punts - not the master for dev:{} ",
+ deviceId);
+ return;
+ }
+
+ ForwardingObjective.Builder puntArp = DefaultForwardingObjective.builder();
+ TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
+ sbuilder.matchEthType(Ethernet.TYPE_ARP);
+ tbuilder.setOutput(PortNumber.CONTROLLER);
+ puntArp.withSelector(sbuilder.build());
+ puntArp.withTreatment(tbuilder.build());
+ puntArp.withFlag(Flag.VERSATILE)
+ .withPriority(HIGHEST_PRIORITY)
+ .makePermanent()
+ .fromApp(srManager.appId);
+ log.debug("Installing forwarding objective to punt ARPs");
+ srManager.flowObjectiveService.
+ forward(deviceId,
+ puntArp.add(new SRObjectiveContext(deviceId,
+ SRObjectiveContext.ObjectiveType.FORWARDING)));
+ }
+
+ /**
* Populates a forwarding objective to send packets that miss other high
* priority Bridging Table entries to a group that contains all ports of
* its subnet.
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index f6bf649..518bce3 100644
--- a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -185,7 +185,7 @@
}
};
- private final HostListener hostListener = new InternalHostListener();
+ private final InternalHostListener hostListener = new InternalHostListener();
private Object threadSchedulerLock = new Object();
private static int numOfEventsQueued = 0;
@@ -658,6 +658,7 @@
// port addressing rules to the driver as well irrespective of whether
// this instance is the master or not.
defaultRoutingHandler.populatePortAddressingRules(device.id());
+ hostListener.readInitialHosts();
}
if (mastershipService.isLocalMaster(device.id())) {
DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
@@ -725,6 +726,7 @@
// port addressing rules to the driver as well, irrespective of whether
// this instance is the master or not.
defaultRoutingHandler.populatePortAddressingRules(device.id());
+ hostListener.readInitialHosts();
}
if (mastershipService.isLocalMaster(device.id())) {
DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
@@ -751,7 +753,34 @@
}
}
+ // TODO Move bridging table population to a separate class
private class InternalHostListener implements HostListener {
+ private void readInitialHosts() {
+ hostService.getHosts().forEach(host -> {
+ MacAddress mac = host.mac();
+ VlanId vlanId = host.vlan();
+ DeviceId deviceId = host.location().deviceId();
+ PortNumber port = host.location().port();
+ Set<IpAddress> ips = host.ipAddresses();
+ log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port);
+
+ // Populate bridging table entry
+ ForwardingObjective.Builder fob =
+ getForwardingObjectiveBuilder(mac, vlanId, port);
+ flowObjectiveService.forward(deviceId, fob.add(
+ new BridgingTableObjectiveContext(mac, vlanId)
+ ));
+
+ // Populate IP table entry
+ ips.forEach(ip -> {
+ if (ip.isIp4()) {
+ routingRulePopulator.populateIpRuleForHost(
+ deviceId, ip.getIp4Address(), mac, port);
+ }
+ });
+ });
+ }
+
private ForwardingObjective.Builder getForwardingObjectiveBuilder(
MacAddress mac, VlanId vlanId, PortNumber port) {
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
@@ -780,7 +809,6 @@
Set<IpAddress> ips = event.subject().ipAddresses();
log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port);
- // TODO Move bridging table population to a separate class
// Populate bridging table entry
ForwardingObjective.Builder fob =
getForwardingObjectiveBuilder(mac, vlanId, port);