Charles Chan
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
...@@ -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 }
......
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 +}