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