Committed by
Ray Milkey
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
Showing
11 changed files
with
724 additions
and
45 deletions
| ... | @@ -513,6 +513,7 @@ public class DefaultRoutingHandler { | ... | @@ -513,6 +513,7 @@ public class DefaultRoutingHandler { |
| 513 | public void populatePortAddressingRules(DeviceId deviceId) { | 513 | public void populatePortAddressingRules(DeviceId deviceId) { |
| 514 | rulePopulator.populateRouterMacVlanFilters(deviceId); | 514 | rulePopulator.populateRouterMacVlanFilters(deviceId); |
| 515 | rulePopulator.populateRouterIpPunts(deviceId); | 515 | rulePopulator.populateRouterIpPunts(deviceId); |
| 516 | + rulePopulator.populateArpPunts(deviceId); | ||
| 516 | } | 517 | } |
| 517 | 518 | ||
| 518 | /** | 519 | /** | ... | ... |
| ... | @@ -511,6 +511,39 @@ public class RoutingRulePopulator { | ... | @@ -511,6 +511,39 @@ public class RoutingRulePopulator { |
| 511 | } | 511 | } |
| 512 | 512 | ||
| 513 | /** | 513 | /** |
| 514 | + * Creates a forwarding objective to punt all IP packets, destined to the | ||
| 515 | + * router's port IP addresses, to the controller. Note that the input | ||
| 516 | + * port should not be matched on, as these packets can come from any input. | ||
| 517 | + * Furthermore, these are applied only by the master instance. | ||
| 518 | + * | ||
| 519 | + * @param deviceId the switch dpid for the router | ||
| 520 | + */ | ||
| 521 | + public void populateArpPunts(DeviceId deviceId) { | ||
| 522 | + if (!srManager.mastershipService.isLocalMaster(deviceId)) { | ||
| 523 | + log.debug("Not installing port-IP punts - not the master for dev:{} ", | ||
| 524 | + deviceId); | ||
| 525 | + return; | ||
| 526 | + } | ||
| 527 | + | ||
| 528 | + ForwardingObjective.Builder puntArp = DefaultForwardingObjective.builder(); | ||
| 529 | + TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); | ||
| 530 | + TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder(); | ||
| 531 | + sbuilder.matchEthType(Ethernet.TYPE_ARP); | ||
| 532 | + tbuilder.setOutput(PortNumber.CONTROLLER); | ||
| 533 | + puntArp.withSelector(sbuilder.build()); | ||
| 534 | + puntArp.withTreatment(tbuilder.build()); | ||
| 535 | + puntArp.withFlag(Flag.VERSATILE) | ||
| 536 | + .withPriority(HIGHEST_PRIORITY) | ||
| 537 | + .makePermanent() | ||
| 538 | + .fromApp(srManager.appId); | ||
| 539 | + log.debug("Installing forwarding objective to punt ARPs"); | ||
| 540 | + srManager.flowObjectiveService. | ||
| 541 | + forward(deviceId, | ||
| 542 | + puntArp.add(new SRObjectiveContext(deviceId, | ||
| 543 | + SRObjectiveContext.ObjectiveType.FORWARDING))); | ||
| 544 | + } | ||
| 545 | + | ||
| 546 | + /** | ||
| 514 | * Populates a forwarding objective to send packets that miss other high | 547 | * Populates a forwarding objective to send packets that miss other high |
| 515 | * priority Bridging Table entries to a group that contains all ports of | 548 | * priority Bridging Table entries to a group that contains all ports of |
| 516 | * its subnet. | 549 | * its subnet. | ... | ... |
| ... | @@ -185,7 +185,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -185,7 +185,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 185 | } | 185 | } |
| 186 | }; | 186 | }; |
| 187 | 187 | ||
| 188 | - private final HostListener hostListener = new InternalHostListener(); | 188 | + private final InternalHostListener hostListener = new InternalHostListener(); |
| 189 | 189 | ||
| 190 | private Object threadSchedulerLock = new Object(); | 190 | private Object threadSchedulerLock = new Object(); |
| 191 | private static int numOfEventsQueued = 0; | 191 | private static int numOfEventsQueued = 0; |
| ... | @@ -658,6 +658,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -658,6 +658,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 658 | // port addressing rules to the driver as well irrespective of whether | 658 | // port addressing rules to the driver as well irrespective of whether |
| 659 | // this instance is the master or not. | 659 | // this instance is the master or not. |
| 660 | defaultRoutingHandler.populatePortAddressingRules(device.id()); | 660 | defaultRoutingHandler.populatePortAddressingRules(device.id()); |
| 661 | + hostListener.readInitialHosts(); | ||
| 661 | } | 662 | } |
| 662 | if (mastershipService.isLocalMaster(device.id())) { | 663 | if (mastershipService.isLocalMaster(device.id())) { |
| 663 | DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); | 664 | DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); |
| ... | @@ -725,6 +726,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -725,6 +726,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 725 | // port addressing rules to the driver as well, irrespective of whether | 726 | // port addressing rules to the driver as well, irrespective of whether |
| 726 | // this instance is the master or not. | 727 | // this instance is the master or not. |
| 727 | defaultRoutingHandler.populatePortAddressingRules(device.id()); | 728 | defaultRoutingHandler.populatePortAddressingRules(device.id()); |
| 729 | + hostListener.readInitialHosts(); | ||
| 728 | } | 730 | } |
| 729 | if (mastershipService.isLocalMaster(device.id())) { | 731 | if (mastershipService.isLocalMaster(device.id())) { |
| 730 | DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); | 732 | DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); |
| ... | @@ -751,7 +753,34 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -751,7 +753,34 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 751 | } | 753 | } |
| 752 | } | 754 | } |
| 753 | 755 | ||
| 756 | + // TODO Move bridging table population to a separate class | ||
| 754 | private class InternalHostListener implements HostListener { | 757 | private class InternalHostListener implements HostListener { |
| 758 | + private void readInitialHosts() { | ||
| 759 | + hostService.getHosts().forEach(host -> { | ||
| 760 | + MacAddress mac = host.mac(); | ||
| 761 | + VlanId vlanId = host.vlan(); | ||
| 762 | + DeviceId deviceId = host.location().deviceId(); | ||
| 763 | + PortNumber port = host.location().port(); | ||
| 764 | + Set<IpAddress> ips = host.ipAddresses(); | ||
| 765 | + log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port); | ||
| 766 | + | ||
| 767 | + // Populate bridging table entry | ||
| 768 | + ForwardingObjective.Builder fob = | ||
| 769 | + getForwardingObjectiveBuilder(mac, vlanId, port); | ||
| 770 | + flowObjectiveService.forward(deviceId, fob.add( | ||
| 771 | + new BridgingTableObjectiveContext(mac, vlanId) | ||
| 772 | + )); | ||
| 773 | + | ||
| 774 | + // Populate IP table entry | ||
| 775 | + ips.forEach(ip -> { | ||
| 776 | + if (ip.isIp4()) { | ||
| 777 | + routingRulePopulator.populateIpRuleForHost( | ||
| 778 | + deviceId, ip.getIp4Address(), mac, port); | ||
| 779 | + } | ||
| 780 | + }); | ||
| 781 | + }); | ||
| 782 | + } | ||
| 783 | + | ||
| 755 | private ForwardingObjective.Builder getForwardingObjectiveBuilder( | 784 | private ForwardingObjective.Builder getForwardingObjectiveBuilder( |
| 756 | MacAddress mac, VlanId vlanId, PortNumber port) { | 785 | MacAddress mac, VlanId vlanId, PortNumber port) { |
| 757 | TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); | 786 | TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); |
| ... | @@ -780,7 +809,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -780,7 +809,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
| 780 | Set<IpAddress> ips = event.subject().ipAddresses(); | 809 | Set<IpAddress> ips = event.subject().ipAddresses(); |
| 781 | log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port); | 810 | log.debug("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port); |
| 782 | 811 | ||
| 783 | - // TODO Move bridging table population to a separate class | ||
| 784 | // Populate bridging table entry | 812 | // Populate bridging table entry |
| 785 | ForwardingObjective.Builder fob = | 813 | ForwardingObjective.Builder fob = |
| 786 | getForwardingObjectiveBuilder(mac, vlanId, port); | 814 | getForwardingObjectiveBuilder(mac, vlanId, port); | ... | ... |
| ... | @@ -15,13 +15,83 @@ | ... | @@ -15,13 +15,83 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onosproject.net.config.basics; | 16 | package org.onosproject.net.config.basics; |
| 17 | 17 | ||
| 18 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
| 19 | +import org.onlab.packet.IpAddress; | ||
| 20 | +import org.onosproject.net.ConnectPoint; | ||
| 18 | import org.onosproject.net.HostId; | 21 | import org.onosproject.net.HostId; |
| 22 | +import java.util.HashSet; | ||
| 23 | +import java.util.Set; | ||
| 19 | 24 | ||
| 20 | /** | 25 | /** |
| 21 | * Basic configuration for network end-station hosts. | 26 | * Basic configuration for network end-station hosts. |
| 22 | */ | 27 | */ |
| 23 | public class BasicHostConfig extends BasicElementConfig<HostId> { | 28 | public class BasicHostConfig extends BasicElementConfig<HostId> { |
| 29 | + private static final String IPS = "ips"; | ||
| 30 | + private static final String LOCATION = "location"; | ||
| 24 | 31 | ||
| 25 | - // TODO: determine what aspects of configuration to add for hosts | 32 | + @Override |
| 33 | + public boolean isValid() { | ||
| 34 | + return hasOnlyFields(IPS, LOCATION) && | ||
| 35 | + this.location() != null && | ||
| 36 | + this.ipAddresses() != null; | ||
| 37 | + } | ||
| 26 | 38 | ||
| 39 | + /** | ||
| 40 | + * Gets location of the host. | ||
| 41 | + * | ||
| 42 | + * @return location of the host. Or null if not specified with correct format. | ||
| 43 | + */ | ||
| 44 | + public ConnectPoint location() { | ||
| 45 | + String location = get(LOCATION, null); | ||
| 46 | + | ||
| 47 | + if (location != null) { | ||
| 48 | + try { | ||
| 49 | + return ConnectPoint.deviceConnectPoint(location); | ||
| 50 | + } catch (Exception e) { | ||
| 51 | + return null; | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + return null; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + /** | ||
| 58 | + * Sets the location of the host. | ||
| 59 | + * | ||
| 60 | + * @param location location of the host. | ||
| 61 | + * @return the config of the host. | ||
| 62 | + */ | ||
| 63 | + public BasicHostConfig setLocation(String location) { | ||
| 64 | + return (BasicHostConfig) setOrClear(LOCATION, location); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * Gets IP addresses of the host. | ||
| 69 | + * | ||
| 70 | + * @return IP addresses of the host. Or null if not specified with correct format. | ||
| 71 | + */ | ||
| 72 | + public Set<IpAddress> ipAddresses() { | ||
| 73 | + HashSet<IpAddress> ipAddresses = new HashSet<>(); | ||
| 74 | + if (object.has(IPS)) { | ||
| 75 | + ArrayNode ipNodes = (ArrayNode) object.path(IPS); | ||
| 76 | + try { | ||
| 77 | + ipNodes.forEach(ipNode -> { | ||
| 78 | + ipAddresses.add(IpAddress.valueOf(ipNode.asText())); | ||
| 79 | + }); | ||
| 80 | + return ipAddresses; | ||
| 81 | + } catch (Exception e) { | ||
| 82 | + return null; | ||
| 83 | + } | ||
| 84 | + } | ||
| 85 | + return null; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + /** | ||
| 89 | + * Sets the IP addresses of the host. | ||
| 90 | + * | ||
| 91 | + * @param ipAddresses IP addresses of the host. | ||
| 92 | + * @return the config of the host. | ||
| 93 | + */ | ||
| 94 | + public BasicHostConfig setIps(Set<IpAddress> ipAddresses) { | ||
| 95 | + return (BasicHostConfig) setOrClear(IPS, ipAddresses); | ||
| 96 | + } | ||
| 27 | } | 97 | } | ... | ... |
providers/netcfghost/pom.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<!-- | ||
| 3 | + ~ Copyright 2014 Open Networking Laboratory | ||
| 4 | + ~ | ||
| 5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 6 | + ~ you may not use this file except in compliance with the License. | ||
| 7 | + ~ You may obtain a copy of the License at | ||
| 8 | + ~ | ||
| 9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
| 10 | + ~ | ||
| 11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
| 12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
| 13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 14 | + ~ See the License for the specific language governing permissions and | ||
| 15 | + ~ limitations under the License. | ||
| 16 | + --> | ||
| 17 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| 18 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| 20 | + <parent> | ||
| 21 | + <artifactId>onos-providers</artifactId> | ||
| 22 | + <groupId>org.onosproject</groupId> | ||
| 23 | + <version>1.4.0-SNAPSHOT</version> | ||
| 24 | + </parent> | ||
| 25 | + <modelVersion>4.0.0</modelVersion> | ||
| 26 | + | ||
| 27 | + <artifactId>onos-netcfg-host-provider</artifactId> | ||
| 28 | + <packaging>bundle</packaging> | ||
| 29 | + | ||
| 30 | + <description> | ||
| 31 | + Host provider that uses network config service to discover hosts. | ||
| 32 | + </description> | ||
| 33 | + <url>http://onosproject.org</url> | ||
| 34 | + | ||
| 35 | + <properties> | ||
| 36 | + <onos.version>1.4.0-SNAPSHOT</onos.version> | ||
| 37 | + <onos.app.name>org.onosproject.netcfghostprovider</onos.app.name> | ||
| 38 | + <onos.app.origin>ON.Lab</onos.app.origin> | ||
| 39 | + </properties> | ||
| 40 | + | ||
| 41 | + <dependencies> | ||
| 42 | + <dependency> | ||
| 43 | + <groupId>org.onosproject</groupId> | ||
| 44 | + <artifactId>onos-api</artifactId> | ||
| 45 | + <version>${onos.version}</version> | ||
| 46 | + </dependency> | ||
| 47 | + | ||
| 48 | + <dependency> | ||
| 49 | + <groupId>org.onosproject</groupId> | ||
| 50 | + <artifactId>onlab-osgi</artifactId> | ||
| 51 | + <version>${onos.version}</version> | ||
| 52 | + </dependency> | ||
| 53 | + | ||
| 54 | + <dependency> | ||
| 55 | + <groupId>junit</groupId> | ||
| 56 | + <artifactId>junit</artifactId> | ||
| 57 | + <version>4.11</version> | ||
| 58 | + <scope>test</scope> | ||
| 59 | + </dependency> | ||
| 60 | + | ||
| 61 | + <dependency> | ||
| 62 | + <groupId>org.onosproject</groupId> | ||
| 63 | + <artifactId>onos-api</artifactId> | ||
| 64 | + <version>${onos.version}</version> | ||
| 65 | + <scope>test</scope> | ||
| 66 | + <classifier>tests</classifier> | ||
| 67 | + </dependency> | ||
| 68 | + | ||
| 69 | + <dependency> | ||
| 70 | + <groupId>org.easymock</groupId> | ||
| 71 | + <artifactId>easymock</artifactId> | ||
| 72 | + <scope>test</scope> | ||
| 73 | + </dependency> | ||
| 74 | + </dependencies> | ||
| 75 | + | ||
| 76 | +</project> |
| 1 | +/* | ||
| 2 | + * Copyright 2014-2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +package org.onosproject.provider.netcfghost; | ||
| 18 | + | ||
| 19 | +import org.apache.felix.scr.annotations.Activate; | ||
| 20 | +import org.apache.felix.scr.annotations.Component; | ||
| 21 | +import org.apache.felix.scr.annotations.Deactivate; | ||
| 22 | +import org.apache.felix.scr.annotations.Reference; | ||
| 23 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
| 24 | +import org.onlab.packet.IpAddress; | ||
| 25 | +import org.onlab.packet.MacAddress; | ||
| 26 | +import org.onlab.packet.VlanId; | ||
| 27 | +import org.onosproject.core.ApplicationId; | ||
| 28 | +import org.onosproject.core.CoreService; | ||
| 29 | +import org.onosproject.net.ConnectPoint; | ||
| 30 | +import org.onosproject.net.Host; | ||
| 31 | +import org.onosproject.net.HostId; | ||
| 32 | +import org.onosproject.net.HostLocation; | ||
| 33 | +import org.onosproject.net.config.NetworkConfigEvent; | ||
| 34 | +import org.onosproject.net.config.NetworkConfigListener; | ||
| 35 | +import org.onosproject.net.config.NetworkConfigRegistry; | ||
| 36 | +import org.onosproject.net.config.basics.BasicHostConfig; | ||
| 37 | +import org.onosproject.net.host.DefaultHostDescription; | ||
| 38 | +import org.onosproject.net.host.HostDescription; | ||
| 39 | +import org.onosproject.net.host.HostProvider; | ||
| 40 | +import org.onosproject.net.host.HostProviderRegistry; | ||
| 41 | +import org.onosproject.net.host.HostProviderService; | ||
| 42 | +import org.onosproject.net.provider.AbstractProvider; | ||
| 43 | +import org.onosproject.net.provider.ProviderId; | ||
| 44 | +import org.slf4j.Logger; | ||
| 45 | +import org.slf4j.LoggerFactory; | ||
| 46 | +import java.util.Set; | ||
| 47 | + | ||
| 48 | +/** | ||
| 49 | + * Host provider that uses network config service to discover hosts. | ||
| 50 | + */ | ||
| 51 | +@Component(immediate = true) | ||
| 52 | +public class NetworkConfigHostProvider extends AbstractProvider implements HostProvider { | ||
| 53 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 54 | + protected CoreService coreService; | ||
| 55 | + | ||
| 56 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 57 | + protected HostProviderRegistry providerRegistry; | ||
| 58 | + | ||
| 59 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 60 | + protected NetworkConfigRegistry networkConfigRegistry; | ||
| 61 | + | ||
| 62 | + private static final String APP_NAME = "org.onosproject.provider.netcfghost"; | ||
| 63 | + private ApplicationId appId; | ||
| 64 | + protected HostProviderService providerService; | ||
| 65 | + | ||
| 66 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
| 67 | + private final InternalNetworkConfigListener networkConfigListener = | ||
| 68 | + new InternalNetworkConfigListener(); | ||
| 69 | + | ||
| 70 | + /** | ||
| 71 | + * Creates an network config host location provider. | ||
| 72 | + */ | ||
| 73 | + public NetworkConfigHostProvider() { | ||
| 74 | + super(new ProviderId("host", APP_NAME)); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @Activate | ||
| 78 | + protected void activate() { | ||
| 79 | + appId = coreService.registerApplication(APP_NAME); | ||
| 80 | + providerService = providerRegistry.register(this); | ||
| 81 | + networkConfigRegistry.addListener(networkConfigListener); | ||
| 82 | + readInitialConfig(); | ||
| 83 | + log.info("Started"); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + @Deactivate | ||
| 87 | + protected void deactivate() { | ||
| 88 | + networkConfigRegistry.removeListener(networkConfigListener); | ||
| 89 | + providerRegistry.unregister(this); | ||
| 90 | + providerService = null; | ||
| 91 | + log.info("Stopped"); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + @Override | ||
| 95 | + public void triggerProbe(Host host) { | ||
| 96 | + /* | ||
| 97 | + * Note: In CORD deployment, we assume that all hosts are configured. | ||
| 98 | + * Therefore no probe is required. | ||
| 99 | + */ | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + /** | ||
| 103 | + * Adds host information. | ||
| 104 | + * IP information will be appended if host exists. | ||
| 105 | + * | ||
| 106 | + * @param mac MAC address of the host | ||
| 107 | + * @param vlan VLAN ID of the host | ||
| 108 | + * @param hloc Location of the host | ||
| 109 | + * @param ips Set of IP addresses of the host | ||
| 110 | + */ | ||
| 111 | + protected void addHost(MacAddress mac, VlanId vlan, HostLocation hloc, Set<IpAddress> ips) { | ||
| 112 | + HostId hid = HostId.hostId(mac, vlan); | ||
| 113 | + HostDescription desc = new DefaultHostDescription(mac, vlan, hloc, ips); | ||
| 114 | + providerService.hostDetected(hid, desc, false); | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + /** | ||
| 118 | + * Updates host information. | ||
| 119 | + * IP information will be replaced if host exists. | ||
| 120 | + * | ||
| 121 | + * @param mac MAC address of the host | ||
| 122 | + * @param vlan VLAN ID of the host | ||
| 123 | + * @param hloc Location of the host | ||
| 124 | + * @param ips Set of IP addresses of the host | ||
| 125 | + */ | ||
| 126 | + protected void updateHost(MacAddress mac, VlanId vlan, HostLocation hloc, Set<IpAddress> ips) { | ||
| 127 | + HostId hid = HostId.hostId(mac, vlan); | ||
| 128 | + HostDescription desc = new DefaultHostDescription(mac, vlan, hloc, ips); | ||
| 129 | + providerService.hostDetected(hid, desc, true); | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + /** | ||
| 133 | + * Removes host information. | ||
| 134 | + * | ||
| 135 | + * @param mac MAC address of the host | ||
| 136 | + * @param vlan VLAN ID of the host | ||
| 137 | + */ | ||
| 138 | + protected void removeHost(MacAddress mac, VlanId vlan) { | ||
| 139 | + HostId hid = HostId.hostId(mac, vlan); | ||
| 140 | + providerService.hostVanished(hid); | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + private void readInitialConfig() { | ||
| 144 | + networkConfigRegistry.getSubjects(HostId.class).forEach(hostId -> { | ||
| 145 | + MacAddress mac = hostId.mac(); | ||
| 146 | + VlanId vlan = hostId.vlanId(); | ||
| 147 | + BasicHostConfig hostConfig = | ||
| 148 | + networkConfigRegistry.getConfig(hostId, BasicHostConfig.class); | ||
| 149 | + Set<IpAddress> ipAddresses = hostConfig.ipAddresses(); | ||
| 150 | + ConnectPoint location = hostConfig.location(); | ||
| 151 | + HostLocation hloc = new HostLocation(location, System.currentTimeMillis()); | ||
| 152 | + addHost(mac, vlan, hloc, ipAddresses); | ||
| 153 | + }); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + private class InternalNetworkConfigListener implements NetworkConfigListener { | ||
| 157 | + @Override | ||
| 158 | + public void event(NetworkConfigEvent event) { | ||
| 159 | + // Do not process non-host, register and unregister events | ||
| 160 | + if (!event.configClass().equals(BasicHostConfig.class) || | ||
| 161 | + event.type() == NetworkConfigEvent.Type.CONFIG_REGISTERED || | ||
| 162 | + event.type() == NetworkConfigEvent.Type.CONFIG_UNREGISTERED) { | ||
| 163 | + return; | ||
| 164 | + } | ||
| 165 | + | ||
| 166 | + HostId hostId = (HostId) event.subject(); | ||
| 167 | + MacAddress mac = hostId.mac(); | ||
| 168 | + VlanId vlan = hostId.vlanId(); | ||
| 169 | + BasicHostConfig hostConfig = | ||
| 170 | + networkConfigRegistry.getConfig(hostId, BasicHostConfig.class); | ||
| 171 | + Set<IpAddress> ipAddresses = null; | ||
| 172 | + HostLocation hloc = null; | ||
| 173 | + | ||
| 174 | + // Note: There will be no config presented in the CONFIG_REMOVE case | ||
| 175 | + if (hostConfig != null) { | ||
| 176 | + ipAddresses = hostConfig.ipAddresses(); | ||
| 177 | + ConnectPoint location = hostConfig.location(); | ||
| 178 | + hloc = new HostLocation(location, System.currentTimeMillis()); | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + switch (event.type()) { | ||
| 182 | + case CONFIG_ADDED: | ||
| 183 | + addHost(mac, vlan, hloc, ipAddresses); | ||
| 184 | + break; | ||
| 185 | + case CONFIG_UPDATED: | ||
| 186 | + updateHost(mac, vlan, hloc, ipAddresses); | ||
| 187 | + break; | ||
| 188 | + case CONFIG_REMOVED: | ||
| 189 | + removeHost(mac, vlan); | ||
| 190 | + break; | ||
| 191 | + default: | ||
| 192 | + break; | ||
| 193 | + } | ||
| 194 | + } | ||
| 195 | + } | ||
| 196 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014-2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * Host provider that uses network config service to discover hosts. | ||
| 19 | + */ | ||
| 20 | +package org.onosproject.provider.netcfghost; |
| 1 | +/* | ||
| 2 | + * Copyright 2014-2015 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +package org.onosproject.provider.netcfghost; | ||
| 18 | + | ||
| 19 | +import org.junit.Before; | ||
| 20 | +import org.junit.Test; | ||
| 21 | +import org.onlab.packet.IpAddress; | ||
| 22 | +import org.onlab.packet.MacAddress; | ||
| 23 | +import org.onlab.packet.VlanId; | ||
| 24 | +import org.onosproject.net.DeviceId; | ||
| 25 | +import org.onosproject.net.HostId; | ||
| 26 | +import org.onosproject.net.HostLocation; | ||
| 27 | +import org.onosproject.net.PortNumber; | ||
| 28 | +import org.onosproject.net.host.DefaultHostDescription; | ||
| 29 | +import org.onosproject.net.host.HostDescription; | ||
| 30 | +import org.onosproject.net.host.HostProvider; | ||
| 31 | +import org.onosproject.net.host.HostProviderService; | ||
| 32 | +import org.onosproject.net.provider.AbstractProviderService; | ||
| 33 | + | ||
| 34 | +import java.util.HashSet; | ||
| 35 | +import java.util.Set; | ||
| 36 | + | ||
| 37 | +import static org.hamcrest.Matchers.is; | ||
| 38 | +import static org.junit.Assert.assertNull; | ||
| 39 | +import static org.junit.Assert.assertThat; | ||
| 40 | + | ||
| 41 | +/** | ||
| 42 | + * Set of tests of the host location provider for CORD. | ||
| 43 | + */ | ||
| 44 | +public class NetworkConfigHostProviderTest { | ||
| 45 | + private NetworkConfigHostProvider provider = new NetworkConfigHostProvider(); | ||
| 46 | + private MockHostProviderService providerService = new MockHostProviderService(provider); | ||
| 47 | + | ||
| 48 | + private MacAddress mac = MacAddress.valueOf("c0:ff:ee:c0:ff:ee"); | ||
| 49 | + private VlanId vlan = VlanId.vlanId(VlanId.UNTAGGED); | ||
| 50 | + private DeviceId deviceId = DeviceId.deviceId("of:0000000000000001"); | ||
| 51 | + private PortNumber port = PortNumber.portNumber(5); | ||
| 52 | + private HostLocation hloc = new HostLocation(deviceId, port, 100); | ||
| 53 | + private Set<IpAddress> ips = new HashSet<>(); | ||
| 54 | + private HostId hostId = HostId.hostId(mac, vlan); | ||
| 55 | + private HostDescription hostDescription; | ||
| 56 | + | ||
| 57 | + @Before | ||
| 58 | + public void setUp() { | ||
| 59 | + provider.providerService = providerService; | ||
| 60 | + | ||
| 61 | + // Initialize test variables | ||
| 62 | + ips.add(IpAddress.valueOf("10.0.0.1")); | ||
| 63 | + ips.add(IpAddress.valueOf("192.168.0.1")); | ||
| 64 | + hostDescription = new DefaultHostDescription(mac, vlan, hloc, ips); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + @Test | ||
| 68 | + public void testAddHost() throws Exception { | ||
| 69 | + provider.addHost(mac, vlan, hloc, ips); | ||
| 70 | + assertThat(providerService.hostId, is(hostId)); | ||
| 71 | + assertThat(providerService.hostDescription, is(hostDescription)); | ||
| 72 | + assertThat(providerService.event, is("hostDetected")); | ||
| 73 | + providerService.clear(); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + @Test | ||
| 77 | + public void testUpdateHost() throws Exception { | ||
| 78 | + provider.updateHost(mac, vlan, hloc, ips); | ||
| 79 | + assertThat(providerService.hostId, is(hostId)); | ||
| 80 | + assertThat(providerService.hostDescription, is(hostDescription)); | ||
| 81 | + assertThat(providerService.event, is("hostDetected")); | ||
| 82 | + providerService.clear(); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + @Test | ||
| 86 | + public void testRemoveHost() throws Exception { | ||
| 87 | + provider.removeHost(mac, vlan); | ||
| 88 | + assertThat(providerService.hostId, is(hostId)); | ||
| 89 | + assertNull(providerService.hostDescription); | ||
| 90 | + assertThat(providerService.event, is("hostVanished")); | ||
| 91 | + providerService.clear(); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + /** | ||
| 95 | + * Mock HostProviderService. | ||
| 96 | + */ | ||
| 97 | + private class MockHostProviderService | ||
| 98 | + extends AbstractProviderService<HostProvider> | ||
| 99 | + implements HostProviderService { | ||
| 100 | + private HostId hostId = null; | ||
| 101 | + private HostDescription hostDescription = null; | ||
| 102 | + private String event = null; | ||
| 103 | + | ||
| 104 | + public MockHostProviderService(HostProvider provider) { | ||
| 105 | + super(provider); | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + @Override | ||
| 109 | + public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) { | ||
| 110 | + this.hostId = hostId; | ||
| 111 | + this.hostDescription = hostDescription; | ||
| 112 | + this.event = "hostDetected"; | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + @Override | ||
| 116 | + public void hostVanished(HostId hostId) { | ||
| 117 | + this.hostId = hostId; | ||
| 118 | + this.event = "hostVanished"; | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + @Override | ||
| 122 | + public void removeIpFromHost(HostId hostId, IpAddress ipAddress) { | ||
| 123 | + // Note: This method is never used. | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + public void clear() { | ||
| 127 | + this.hostId = null; | ||
| 128 | + this.hostDescription = null; | ||
| 129 | + this.event = null; | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | +} |
| ... | @@ -35,6 +35,7 @@ | ... | @@ -35,6 +35,7 @@ |
| 35 | <module>openflow</module> | 35 | <module>openflow</module> |
| 36 | <module>lldp</module> | 36 | <module>lldp</module> |
| 37 | <module>host</module> | 37 | <module>host</module> |
| 38 | + <module>netcfghost</module> | ||
| 38 | <module>netconf</module> | 39 | <module>netconf</module> |
| 39 | <module>null</module> | 40 | <module>null</module> |
| 40 | <module>pcep</module> | 41 | <module>pcep</module> | ... | ... |
| 1 | { | 1 | { |
| 2 | "ports" : { | 2 | "ports" : { |
| 3 | - "of:0000000000000002/1" : { | 3 | + "of:0000000000000002/1" : { |
| 4 | - "interfaces" : [ | 4 | + "interfaces" : [ |
| 5 | - { | 5 | + { |
| 6 | - "ips" : [ "192.168.10.101/24" ], | 6 | + "ips" : [ "192.168.10.101/24" ], |
| 7 | - "mac" : "08:9e:01:82:38:68", | 7 | + "mac" : "08:9e:01:82:38:68", |
| 8 | - "vlan" : "100" | 8 | + "vlan" : "100" |
| 9 | - } | 9 | + } |
| 10 | - ] | 10 | + ] |
| 11 | - }, | 11 | + }, |
| 12 | - "of:0000000000000002/20" : { | 12 | + "of:0000000000000002/2" : { |
| 13 | - "interfaces" : [ | 13 | + "interfaces" : [ |
| 14 | - { | 14 | + { |
| 15 | - "ips" : [ "192.168.20.101/24" ], | 15 | + "ips" : [ "192.168.20.101/24" ], |
| 16 | - "mac" : "08:9e:01:82:38:68", | 16 | + "mac" : "08:9e:01:82:38:68", |
| 17 | - "vlan" : "200" | 17 | + "vlan" : "200" |
| 18 | - } | 18 | + } |
| 19 | - ] | 19 | + ] |
| 20 | - } | 20 | + } |
| 21 | }, | 21 | }, |
| 22 | "devices" : { | 22 | "devices" : { |
| 23 | - "of:0000000000000002" : { | 23 | + "of:0000000000000002" : { |
| 24 | - "segmentrouting" : { | 24 | + "segmentrouting" : { |
| 25 | "name" : "Leaf-R1", | 25 | "name" : "Leaf-R1", |
| 26 | "nodeSid" : 101, | 26 | "nodeSid" : 101, |
| 27 | "routerIp" : "10.0.1.254", | 27 | "routerIp" : "10.0.1.254", |
| ... | @@ -32,36 +32,54 @@ | ... | @@ -32,36 +32,54 @@ |
| 32 | { "sid" : 200, "ports" : [4, 5] } | 32 | { "sid" : 200, "ports" : [4, 5] } |
| 33 | ] | 33 | ] |
| 34 | } | 34 | } |
| 35 | - }, | 35 | + }, |
| 36 | - "of:0000000000000191" : { | 36 | + "of:0000000000000191" : { |
| 37 | - "segmentrouting" : { | 37 | + "segmentrouting" : { |
| 38 | "name" : "Spine-R1", | 38 | "name" : "Spine-R1", |
| 39 | "nodeSid" : 105, | 39 | "nodeSid" : 105, |
| 40 | "routerIp" : "192.168.0.11", | 40 | "routerIp" : "192.168.0.11", |
| 41 | "routerMac" : "00:00:01:00:11:80", | 41 | "routerMac" : "00:00:01:00:11:80", |
| 42 | "isEdgeRouter" : false | 42 | "isEdgeRouter" : false |
| 43 | } | 43 | } |
| 44 | - } | 44 | + } |
| 45 | }, | 45 | }, |
| 46 | "apps" : { | 46 | "apps" : { |
| 47 | - "org.onosproject.router" : { | 47 | + "org.onosproject.router" : { |
| 48 | - "bgp" : { | 48 | + "bgp" : { |
| 49 | - "bgpSpeakers" : [ | 49 | + "bgpSpeakers" : [ |
| 50 | - { | 50 | + { |
| 51 | - "connectPoint" : "of:00000000000000aa/10", | 51 | + "connectPoint" : "of:00000000000000aa/10", |
| 52 | - "peers" : [ | 52 | + "peers" : [ |
| 53 | - "192.168.10.1" | 53 | + "192.168.10.1" |
| 54 | - ] | 54 | + ] |
| 55 | - }, | 55 | + }, |
| 56 | - { | 56 | + { |
| 57 | - "connectPoint" : "of:00000000000000aa/20", | 57 | + "connectPoint" : "of:00000000000000aa/20", |
| 58 | - "peers" : [ | 58 | + "peers" : [ |
| 59 | - "192.168.20.1" | 59 | + "192.168.20.1" |
| 60 | - ] | 60 | + ] |
| 61 | - } | 61 | + } |
| 62 | - ] | 62 | + ] |
| 63 | - } | 63 | + } |
| 64 | - } | 64 | + } |
| 65 | + }, | ||
| 66 | + "hosts" : { | ||
| 67 | + "00:00:00:00:00:01/4093": { | ||
| 68 | + "basic": { | ||
| 69 | + "ips": [ | ||
| 70 | + "10.0.1.1" | ||
| 71 | + ], | ||
| 72 | + "location": "of:0000000000000001/3" | ||
| 73 | + } | ||
| 74 | + }, | ||
| 75 | + "00:00:00:00:00:02/4093": { | ||
| 76 | + "basic": { | ||
| 77 | + "ips": [ | ||
| 78 | + "10.0.1.2" | ||
| 79 | + ], | ||
| 80 | + "location": "of:0000000000000001/4" | ||
| 81 | + } | ||
| 82 | + } | ||
| 65 | } | 83 | } |
| 66 | } | 84 | } |
| 67 | 85 | ... | ... |
| 1 | +{ | ||
| 2 | + "ports" : { | ||
| 3 | + "of:0000000000000001/3" : { | ||
| 4 | + "interfaces" : [ | ||
| 5 | + { | ||
| 6 | + "ips" : [ "10.0.1.254/24" ], | ||
| 7 | + "mac" : "08:9e:01:82:38:68", | ||
| 8 | + "vlan" : "100" | ||
| 9 | + } | ||
| 10 | + ] | ||
| 11 | + }, | ||
| 12 | + "of:0000000000000001/4" : { | ||
| 13 | + "interfaces" : [ | ||
| 14 | + { | ||
| 15 | + "ips" : [ "10.0.1.254/24" ], | ||
| 16 | + "mac" : "08:9e:01:82:38:68", | ||
| 17 | + "vlan" : "100" | ||
| 18 | + } | ||
| 19 | + ] | ||
| 20 | + }, | ||
| 21 | + "of:0000000000000002/3" : { | ||
| 22 | + "interfaces" : [ | ||
| 23 | + { | ||
| 24 | + "ips" : [ "10.0.2.254/24" ], | ||
| 25 | + "mac" : "08:9e:01:82:38:68", | ||
| 26 | + "vlan" : "100" | ||
| 27 | + } | ||
| 28 | + ] | ||
| 29 | + }, | ||
| 30 | + "of:0000000000000002/4" : { | ||
| 31 | + "interfaces" : [ | ||
| 32 | + { | ||
| 33 | + "ips" : [ "10.0.2.254/24" ], | ||
| 34 | + "mac" : "08:9e:01:82:38:68", | ||
| 35 | + "vlan" : "100" | ||
| 36 | + } | ||
| 37 | + ] | ||
| 38 | + } | ||
| 39 | + }, | ||
| 40 | + "devices" : { | ||
| 41 | + "of:0000000000000001" : { | ||
| 42 | + "segmentrouting" : { | ||
| 43 | + "name" : "Leaf-R1", | ||
| 44 | + "nodeSid" : 101, | ||
| 45 | + "routerIp" : "10.0.1.254", | ||
| 46 | + "routerMac" : "00:00:00:00:01:80", | ||
| 47 | + "isEdgeRouter" : true | ||
| 48 | + } | ||
| 49 | + }, | ||
| 50 | + "of:0000000000000002" : { | ||
| 51 | + "segmentrouting" : { | ||
| 52 | + "name" : "Leaf-R2", | ||
| 53 | + "nodeSid" : 102, | ||
| 54 | + "routerIp" : "10.0.2.254", | ||
| 55 | + "routerMac" : "00:00:00:00:02:80", | ||
| 56 | + "isEdgeRouter" : true | ||
| 57 | + } | ||
| 58 | + }, | ||
| 59 | + "of:0000000000000191" : { | ||
| 60 | + "segmentrouting" : { | ||
| 61 | + "name" : "Spine-R1", | ||
| 62 | + "nodeSid" : 103, | ||
| 63 | + "routerIp" : "192.168.0.11", | ||
| 64 | + "routerMac" : "00:00:01:00:11:80", | ||
| 65 | + "isEdgeRouter" : false | ||
| 66 | + } | ||
| 67 | + }, | ||
| 68 | + "of:0000000000000192" : { | ||
| 69 | + "segmentrouting" : { | ||
| 70 | + "name" : "Spine-R2", | ||
| 71 | + "nodeSid" : 104, | ||
| 72 | + "routerIp" : "192.168.0.22", | ||
| 73 | + "routerMac" : "00:00:01:00:22:80", | ||
| 74 | + "isEdgeRouter" : false | ||
| 75 | + } | ||
| 76 | + } | ||
| 77 | + }, | ||
| 78 | + "hosts" : { | ||
| 79 | + "00:00:00:00:00:01/4093" : { | ||
| 80 | + "basic": { | ||
| 81 | + "ips": ["10.0.1.1"], | ||
| 82 | + "location": "of:0000000000000001/3" | ||
| 83 | + } | ||
| 84 | + }, | ||
| 85 | + "00:00:00:00:00:02/4093" : { | ||
| 86 | + "basic": { | ||
| 87 | + "ips": ["10.0.1.2"], | ||
| 88 | + "location": "of:0000000000000001/4" | ||
| 89 | + } | ||
| 90 | + }, | ||
| 91 | + "00:00:00:00:00:03/4093" : { | ||
| 92 | + "basic": { | ||
| 93 | + "ips": ["10.0.2.1"], | ||
| 94 | + "location": "of:0000000000000002/3" | ||
| 95 | + } | ||
| 96 | + }, | ||
| 97 | + "00:00:00:00:00:04/4093" : { | ||
| 98 | + "basic": { | ||
| 99 | + "ips": ["10.0.2.2"], | ||
| 100 | + "location": "of:0000000000000002/4" | ||
| 101 | + } | ||
| 102 | + } | ||
| 103 | + } | ||
| 104 | +} |
-
Please register or login to post a comment