Committed by
Gerrit Code Review
ONOS-685: Network Configuration Manager support for Segment Routing application
Change-Id: Ia15bfd24559dd5542633c8b76d500b2d31362340
Showing
25 changed files
with
2077 additions
and
486 deletions
apps/grouphandler/src/main/java/org/onosproject/grouphandler/DefaultGroupHandlerApp.java
deleted
100644 → 0
| 1 | -/* | ||
| 2 | - * Copyright 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 | -package org.onosproject.grouphandler; | ||
| 17 | - | ||
| 18 | -import static org.slf4j.LoggerFactory.getLogger; | ||
| 19 | - | ||
| 20 | -import java.net.URI; | ||
| 21 | -import java.util.Arrays; | ||
| 22 | -import java.util.HashMap; | ||
| 23 | -import java.util.HashSet; | ||
| 24 | -import java.util.List; | ||
| 25 | - | ||
| 26 | -import org.apache.felix.scr.annotations.Activate; | ||
| 27 | -import org.apache.felix.scr.annotations.Component; | ||
| 28 | -import org.apache.felix.scr.annotations.Deactivate; | ||
| 29 | -import org.apache.felix.scr.annotations.Reference; | ||
| 30 | -import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
| 31 | -import org.onlab.packet.MacAddress; | ||
| 32 | -import org.onlab.util.KryoNamespace; | ||
| 33 | -import org.onosproject.core.ApplicationId; | ||
| 34 | -import org.onosproject.core.CoreService; | ||
| 35 | -import org.onosproject.mastership.MastershipService; | ||
| 36 | -import org.onosproject.net.Device; | ||
| 37 | -import org.onosproject.net.DeviceId; | ||
| 38 | -import org.onosproject.net.MastershipRole; | ||
| 39 | -import org.onosproject.net.device.DeviceEvent; | ||
| 40 | -import org.onosproject.net.device.DeviceListener; | ||
| 41 | -import org.onosproject.net.device.DeviceService; | ||
| 42 | -import org.onosproject.net.group.GroupService; | ||
| 43 | -import org.onosproject.net.link.LinkEvent; | ||
| 44 | -import org.onosproject.net.link.LinkListener; | ||
| 45 | -import org.onosproject.net.link.LinkService; | ||
| 46 | -import org.onosproject.net.topology.TopologyService; | ||
| 47 | -import org.slf4j.Logger; | ||
| 48 | - | ||
| 49 | -/** | ||
| 50 | - * Sample application to verify group subsystem end to end. | ||
| 51 | - * This application expects a network of maximum of six connected | ||
| 52 | - * devices for the test to work. For every device in the network, | ||
| 53 | - * this test application launches a default group handler function | ||
| 54 | - * that creates ECMP groups for every neighbor the device is | ||
| 55 | - * connected to. | ||
| 56 | - */ | ||
| 57 | -@Component(immediate = true) | ||
| 58 | -public class DefaultGroupHandlerApp { | ||
| 59 | - | ||
| 60 | - private final Logger log = getLogger(getClass()); | ||
| 61 | - | ||
| 62 | - private final DeviceProperties config = new DeviceConfiguration(); | ||
| 63 | - private ApplicationId appId; | ||
| 64 | - private HashMap<DeviceId, DefaultGroupHandler> dghMap = | ||
| 65 | - new HashMap<DeviceId, DefaultGroupHandler>(); | ||
| 66 | - | ||
| 67 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 68 | - protected TopologyService topologyService; | ||
| 69 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 70 | - protected DeviceService deviceService; | ||
| 71 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 72 | - protected LinkService linkService; | ||
| 73 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 74 | - protected GroupService groupService; | ||
| 75 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 76 | - protected CoreService coreService; | ||
| 77 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 78 | - protected MastershipService mastershipService; | ||
| 79 | - | ||
| 80 | - private DeviceListener deviceListener = new InternalDeviceListener(); | ||
| 81 | - private LinkListener linkListener = new InternalLinkListener(); | ||
| 82 | - | ||
| 83 | - protected KryoNamespace.Builder kryo = new KryoNamespace.Builder() | ||
| 84 | - .register(URI.class) | ||
| 85 | - .register(HashSet.class) | ||
| 86 | - .register(DeviceId.class) | ||
| 87 | - .register(NeighborSet.class); | ||
| 88 | - | ||
| 89 | - @Activate | ||
| 90 | - public void activate() { | ||
| 91 | - appId = coreService.registerApplication("org.onosproject.defaultgrouphandler"); | ||
| 92 | - log.info("DefaultGroupHandlerApp Activating"); | ||
| 93 | - | ||
| 94 | - deviceService.addListener(deviceListener); | ||
| 95 | - linkService.addListener(linkListener); | ||
| 96 | - for (Device device: deviceService.getDevices()) { | ||
| 97 | - if (mastershipService. | ||
| 98 | - getLocalRole(device.id()) == MastershipRole.MASTER) { | ||
| 99 | - log.debug("Initiating default group handling for {}", device.id()); | ||
| 100 | - DefaultGroupHandler dgh = DefaultGroupHandler.createGroupHandler(device.id(), | ||
| 101 | - appId, | ||
| 102 | - config, | ||
| 103 | - linkService, | ||
| 104 | - groupService); | ||
| 105 | - dgh.createGroups(); | ||
| 106 | - dghMap.put(device.id(), dgh); | ||
| 107 | - } else { | ||
| 108 | - log.debug("Activate: Local role {} " | ||
| 109 | - + "is not MASTER for device {}", | ||
| 110 | - mastershipService. | ||
| 111 | - getLocalRole(device.id()), | ||
| 112 | - device.id()); | ||
| 113 | - } | ||
| 114 | - } | ||
| 115 | - | ||
| 116 | - log.info("Activated"); | ||
| 117 | - } | ||
| 118 | - | ||
| 119 | - @Deactivate | ||
| 120 | - public void deactivate() { | ||
| 121 | - dghMap.clear(); | ||
| 122 | - } | ||
| 123 | - | ||
| 124 | - public class DeviceConfiguration implements DeviceProperties { | ||
| 125 | - private final List<Integer> allSegmentIds = | ||
| 126 | - Arrays.asList(101, 102, 103, 104, 105, 106); | ||
| 127 | - private HashMap<DeviceId, Integer> deviceSegmentIdMap = | ||
| 128 | - new HashMap<DeviceId, Integer>() { | ||
| 129 | - { | ||
| 130 | - put(DeviceId.deviceId("of:0000000000000001"), 101); | ||
| 131 | - put(DeviceId.deviceId("of:0000000000000002"), 102); | ||
| 132 | - put(DeviceId.deviceId("of:0000000000000003"), 103); | ||
| 133 | - put(DeviceId.deviceId("of:0000000000000004"), 104); | ||
| 134 | - put(DeviceId.deviceId("of:0000000000000005"), 105); | ||
| 135 | - put(DeviceId.deviceId("of:0000000000000006"), 106); | ||
| 136 | - } | ||
| 137 | - }; | ||
| 138 | - private final HashMap<DeviceId, MacAddress> deviceMacMap = | ||
| 139 | - new HashMap<DeviceId, MacAddress>() { | ||
| 140 | - { | ||
| 141 | - put(DeviceId.deviceId("of:0000000000000001"), | ||
| 142 | - MacAddress.valueOf("00:00:00:00:00:01")); | ||
| 143 | - put(DeviceId.deviceId("of:0000000000000002"), | ||
| 144 | - MacAddress.valueOf("00:00:00:00:00:02")); | ||
| 145 | - put(DeviceId.deviceId("of:0000000000000003"), | ||
| 146 | - MacAddress.valueOf("00:00:00:00:00:03")); | ||
| 147 | - put(DeviceId.deviceId("of:0000000000000004"), | ||
| 148 | - MacAddress.valueOf("00:00:00:00:00:04")); | ||
| 149 | - put(DeviceId.deviceId("of:0000000000000005"), | ||
| 150 | - MacAddress.valueOf("00:00:00:00:00:05")); | ||
| 151 | - put(DeviceId.deviceId("of:0000000000000006"), | ||
| 152 | - MacAddress.valueOf("00:00:00:00:00:06")); | ||
| 153 | - } | ||
| 154 | - }; | ||
| 155 | - | ||
| 156 | - @Override | ||
| 157 | - public int getSegmentId(DeviceId deviceId) { | ||
| 158 | - if (deviceSegmentIdMap.get(deviceId) != null) { | ||
| 159 | - log.debug("getSegmentId for device{} is {}", | ||
| 160 | - deviceId, | ||
| 161 | - deviceSegmentIdMap.get(deviceId)); | ||
| 162 | - return deviceSegmentIdMap.get(deviceId); | ||
| 163 | - } else { | ||
| 164 | - throw new IllegalStateException(); | ||
| 165 | - } | ||
| 166 | - } | ||
| 167 | - @Override | ||
| 168 | - public MacAddress getDeviceMac(DeviceId deviceId) { | ||
| 169 | - if (deviceMacMap.get(deviceId) != null) { | ||
| 170 | - log.debug("getDeviceMac for device{} is {}", | ||
| 171 | - deviceId, | ||
| 172 | - deviceMacMap.get(deviceId)); | ||
| 173 | - return deviceMacMap.get(deviceId); | ||
| 174 | - } else { | ||
| 175 | - throw new IllegalStateException(); | ||
| 176 | - } | ||
| 177 | - } | ||
| 178 | - @Override | ||
| 179 | - public boolean isEdgeDevice(DeviceId deviceId) { | ||
| 180 | - return true; | ||
| 181 | - } | ||
| 182 | - @Override | ||
| 183 | - public List<Integer> getAllDeviceSegmentIds() { | ||
| 184 | - return allSegmentIds; | ||
| 185 | - } | ||
| 186 | - } | ||
| 187 | - | ||
| 188 | - private class InternalDeviceListener implements DeviceListener { | ||
| 189 | - | ||
| 190 | - @Override | ||
| 191 | - public void event(DeviceEvent event) { | ||
| 192 | - if (mastershipService. | ||
| 193 | - getLocalRole(event.subject().id()) != MastershipRole.MASTER) { | ||
| 194 | - log.debug("Local role {} is not MASTER for device {}", | ||
| 195 | - mastershipService. | ||
| 196 | - getLocalRole(event.subject().id()), | ||
| 197 | - event.subject().id()); | ||
| 198 | - return; | ||
| 199 | - } | ||
| 200 | - switch (event.type()) { | ||
| 201 | - case DEVICE_ADDED: | ||
| 202 | - log.debug("Initiating default group handling for {}", event.subject().id()); | ||
| 203 | - DefaultGroupHandler dgh = DefaultGroupHandler.createGroupHandler( | ||
| 204 | - event.subject().id(), | ||
| 205 | - appId, | ||
| 206 | - config, | ||
| 207 | - linkService, | ||
| 208 | - groupService); | ||
| 209 | - dgh.createGroups(); | ||
| 210 | - dghMap.put(event.subject().id(), dgh); | ||
| 211 | - break; | ||
| 212 | - case PORT_REMOVED: | ||
| 213 | - if (dghMap.get(event.subject().id()) != null) { | ||
| 214 | - dghMap.get(event.subject().id()).portDown(event.port().number()); | ||
| 215 | - } | ||
| 216 | - break; | ||
| 217 | - default: | ||
| 218 | - break; | ||
| 219 | - } | ||
| 220 | - | ||
| 221 | - } | ||
| 222 | - } | ||
| 223 | - | ||
| 224 | - private class InternalLinkListener implements LinkListener { | ||
| 225 | - | ||
| 226 | - @Override | ||
| 227 | - public void event(LinkEvent event) { | ||
| 228 | - if (mastershipService. | ||
| 229 | - getLocalRole(event.subject().src().deviceId()) != | ||
| 230 | - MastershipRole.MASTER) { | ||
| 231 | - log.debug("InternalLinkListener: Local role {} " | ||
| 232 | - + "is not MASTER for device {}", | ||
| 233 | - mastershipService. | ||
| 234 | - getLocalRole(event.subject().src().deviceId()), | ||
| 235 | - event.subject().src().deviceId()); | ||
| 236 | - return; | ||
| 237 | - } | ||
| 238 | - switch (event.type()) { | ||
| 239 | - case LINK_ADDED: | ||
| 240 | - if (dghMap.get(event.subject().src().deviceId()) != null) { | ||
| 241 | - dghMap.get(event.subject().src().deviceId()).linkUp(event.subject()); | ||
| 242 | - } | ||
| 243 | - break; | ||
| 244 | - default: | ||
| 245 | - break; | ||
| 246 | - } | ||
| 247 | - } | ||
| 248 | - | ||
| 249 | - } | ||
| 250 | -} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -45,7 +45,6 @@ | ... | @@ -45,7 +45,6 @@ |
| 45 | <module>reactive-routing</module> | 45 | <module>reactive-routing</module> |
| 46 | <module>bgprouter</module> | 46 | <module>bgprouter</module> |
| 47 | <module>test</module> | 47 | <module>test</module> |
| 48 | - <module>grouphandler</module> | ||
| 49 | <module>segmentrouting</module> | 48 | <module>segmentrouting</module> |
| 50 | </modules> | 49 | </modules> |
| 51 | 50 | ... | ... |
| ... | @@ -19,7 +19,6 @@ import org.onlab.packet.ARP; | ... | @@ -19,7 +19,6 @@ import org.onlab.packet.ARP; |
| 19 | import org.onlab.packet.Ethernet; | 19 | import org.onlab.packet.Ethernet; |
| 20 | import org.onlab.packet.Ip4Address; | 20 | import org.onlab.packet.Ip4Address; |
| 21 | import org.onlab.packet.IpAddress; | 21 | import org.onlab.packet.IpAddress; |
| 22 | -import org.onlab.packet.IpPrefix; | ||
| 23 | import org.onlab.packet.MacAddress; | 22 | import org.onlab.packet.MacAddress; |
| 24 | import org.onosproject.net.ConnectPoint; | 23 | import org.onosproject.net.ConnectPoint; |
| 25 | import org.onosproject.net.DeviceId; | 24 | import org.onosproject.net.DeviceId; |
| ... | @@ -36,7 +35,7 @@ import org.slf4j.Logger; | ... | @@ -36,7 +35,7 @@ import org.slf4j.Logger; |
| 36 | import org.slf4j.LoggerFactory; | 35 | import org.slf4j.LoggerFactory; |
| 37 | 36 | ||
| 38 | import java.nio.ByteBuffer; | 37 | import java.nio.ByteBuffer; |
| 39 | - | 38 | +import java.util.List; |
| 40 | import static com.google.common.base.Preconditions.checkNotNull; | 39 | import static com.google.common.base.Preconditions.checkNotNull; |
| 41 | 40 | ||
| 42 | public class ArpHandler { | 41 | public class ArpHandler { |
| ... | @@ -112,11 +111,11 @@ public class ArpHandler { | ... | @@ -112,11 +111,11 @@ public class ArpHandler { |
| 112 | 111 | ||
| 113 | 112 | ||
| 114 | private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) { | 113 | private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) { |
| 115 | - Ip4Address gatewayIpAddress = config.getGatewayIpAddress(deviceId); | 114 | + List<Ip4Address> gatewayIpAddresses = config.getGatewayIpAddress(deviceId); |
| 116 | - if (gatewayIpAddress != null) { | 115 | + if (gatewayIpAddresses != null) { |
| 117 | Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest | 116 | Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest |
| 118 | .getTargetProtocolAddress()); | 117 | .getTargetProtocolAddress()); |
| 119 | - if (gatewayIpAddress.equals(targetProtocolAddress)) { | 118 | + if (gatewayIpAddresses.contains(targetProtocolAddress)) { |
| 120 | return true; | 119 | return true; |
| 121 | } | 120 | } |
| 122 | } | 121 | } |
| ... | @@ -124,15 +123,11 @@ public class ArpHandler { | ... | @@ -124,15 +123,11 @@ public class ArpHandler { |
| 124 | } | 123 | } |
| 125 | 124 | ||
| 126 | private boolean isArpReqForSubnet(DeviceId deviceId, ARP arpRequest) { | 125 | private boolean isArpReqForSubnet(DeviceId deviceId, ARP arpRequest) { |
| 127 | - String subnetInfo = config.getSubnetInfo(deviceId); | 126 | + return config.getSubnetInfo(deviceId).stream() |
| 128 | - if (subnetInfo != null) { | 127 | + .anyMatch((prefix)-> |
| 129 | - IpPrefix prefix = IpPrefix.valueOf(subnetInfo); | 128 | + prefix.contains(Ip4Address. |
| 130 | - if (prefix.contains(Ip4Address.valueOf(arpRequest.getTargetProtocolAddress()))) { | 129 | + valueOf(arpRequest. |
| 131 | - return true; | 130 | + getTargetProtocolAddress()))); |
| 132 | - } | ||
| 133 | - } | ||
| 134 | - | ||
| 135 | - return false; | ||
| 136 | } | 131 | } |
| 137 | 132 | ||
| 138 | /** | 133 | /** | ... | ... |
| ... | @@ -15,6 +15,7 @@ | ... | @@ -15,6 +15,7 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onosproject.segmentrouting; | 16 | package org.onosproject.segmentrouting; |
| 17 | 17 | ||
| 18 | +import org.onlab.packet.Ip4Prefix; | ||
| 18 | import org.onlab.packet.IpPrefix; | 19 | import org.onlab.packet.IpPrefix; |
| 19 | import org.onosproject.net.Device; | 20 | import org.onosproject.net.Device; |
| 20 | import org.onosproject.net.DeviceId; | 21 | import org.onosproject.net.DeviceId; |
| ... | @@ -26,6 +27,7 @@ import org.slf4j.LoggerFactory; | ... | @@ -26,6 +27,7 @@ import org.slf4j.LoggerFactory; |
| 26 | import java.util.ArrayList; | 27 | import java.util.ArrayList; |
| 27 | import java.util.HashMap; | 28 | import java.util.HashMap; |
| 28 | import java.util.HashSet; | 29 | import java.util.HashSet; |
| 30 | +import java.util.List; | ||
| 29 | import java.util.Set; | 31 | import java.util.Set; |
| 30 | 32 | ||
| 31 | import static com.google.common.base.Preconditions.checkNotNull; | 33 | import static com.google.common.base.Preconditions.checkNotNull; |
| ... | @@ -139,8 +141,11 @@ public class DefaultRoutingHandler { | ... | @@ -139,8 +141,11 @@ public class DefaultRoutingHandler { |
| 139 | // If both target switch and dest switch are edge routers, then set IP rule | 141 | // If both target switch and dest switch are edge routers, then set IP rule |
| 140 | // for both subnet and router IP. | 142 | // for both subnet and router IP. |
| 141 | if (config.isEdgeRouter(targetSw) && config.isEdgeRouter(destSw)) { | 143 | if (config.isEdgeRouter(targetSw) && config.isEdgeRouter(destSw)) { |
| 142 | - String subnets = config.getSubnetInfo(destSw); | 144 | + List<Ip4Prefix> subnets = config.getSubnetInfo(destSw); |
| 143 | - result = rulePopulator.populateIpRuleForSubnet(targetSw, subnets, destSw, nextHops); | 145 | + result = rulePopulator.populateIpRuleForSubnet(targetSw, |
| 146 | + subnets, | ||
| 147 | + destSw, | ||
| 148 | + nextHops); | ||
| 144 | if (!result) { | 149 | if (!result) { |
| 145 | return false; | 150 | return false; |
| 146 | } | 151 | } | ... | ... |
| 1 | package org.onosproject.segmentrouting; | 1 | package org.onosproject.segmentrouting; |
| 2 | 2 | ||
| 3 | import org.onlab.packet.Ip4Address; | 3 | import org.onlab.packet.Ip4Address; |
| 4 | +import org.onlab.packet.Ip4Prefix; | ||
| 5 | +import org.onlab.packet.IpPrefix; | ||
| 4 | import org.onlab.packet.MacAddress; | 6 | import org.onlab.packet.MacAddress; |
| 5 | -import org.onosproject.grouphandler.DeviceProperties; | 7 | +import org.onosproject.segmentrouting.grouphandler.DeviceProperties; |
| 6 | import org.onosproject.net.DeviceId; | 8 | import org.onosproject.net.DeviceId; |
| 9 | +import org.onosproject.net.PortNumber; | ||
| 10 | +import org.onosproject.segmentrouting.config.NetworkConfig.SwitchConfig; | ||
| 11 | +import org.onosproject.segmentrouting.config.NetworkConfigManager; | ||
| 12 | +import org.onosproject.segmentrouting.config.SegmentRouterConfig; | ||
| 13 | +import org.onosproject.segmentrouting.config.SegmentRouterConfig.Subnet; | ||
| 7 | import org.slf4j.Logger; | 14 | import org.slf4j.Logger; |
| 8 | import org.slf4j.LoggerFactory; | 15 | import org.slf4j.LoggerFactory; |
| 9 | 16 | ||
| 10 | -import java.util.Arrays; | 17 | +import static com.google.common.base.Preconditions.checkNotNull; |
| 18 | + | ||
| 19 | +import java.util.ArrayList; | ||
| 11 | import java.util.HashMap; | 20 | import java.util.HashMap; |
| 12 | import java.util.List; | 21 | import java.util.List; |
| 13 | import java.util.Map; | 22 | import java.util.Map; |
| 14 | 23 | ||
| 24 | +/** | ||
| 25 | + * Segment Routing configuration component that reads the | ||
| 26 | + * segment routing related configuration from Network Configuration Manager | ||
| 27 | + * component and organizes in more accessible formats. | ||
| 28 | + * | ||
| 29 | + * TODO: Merge multiple Segment Routing configuration wrapper classes into one. | ||
| 30 | + */ | ||
| 15 | public class DeviceConfiguration implements DeviceProperties { | 31 | public class DeviceConfiguration implements DeviceProperties { |
| 16 | 32 | ||
| 17 | private static final Logger log = LoggerFactory | 33 | private static final Logger log = LoggerFactory |
| 18 | .getLogger(DeviceConfiguration.class); | 34 | .getLogger(DeviceConfiguration.class); |
| 19 | - private final List<Integer> allSegmentIds = | 35 | + private final List<Integer> allSegmentIds = new ArrayList<Integer>(); |
| 20 | - Arrays.asList(101, 102, 103, 104, 105, 106); | 36 | + private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>(); |
| 21 | - private HashMap<DeviceId, Integer> deviceSegmentIdMap = | 37 | + private final NetworkConfigManager configService; |
| 22 | - new HashMap<DeviceId, Integer>() { | 38 | + |
| 23 | - { | 39 | + private class SegmentRouterInfo { |
| 24 | - put(DeviceId.deviceId("of:0000000000000001"), 101); | 40 | + int nodeSid; |
| 25 | - put(DeviceId.deviceId("of:0000000000000002"), 102); | 41 | + DeviceId deviceId; |
| 26 | - put(DeviceId.deviceId("of:0000000000000003"), 103); | 42 | + Ip4Address ip; |
| 27 | - put(DeviceId.deviceId("of:0000000000000004"), 104); | 43 | + MacAddress mac; |
| 28 | - put(DeviceId.deviceId("of:0000000000000005"), 105); | 44 | + boolean isEdge; |
| 29 | - put(DeviceId.deviceId("of:0000000000000006"), 106); | 45 | + HashMap<PortNumber, Ip4Address> gatewayIps; |
| 30 | - } | 46 | + HashMap<PortNumber, Ip4Prefix> subnets; |
| 31 | - }; | 47 | + } |
| 32 | - private final HashMap<DeviceId, MacAddress> deviceMacMap = | 48 | + |
| 33 | - new HashMap<DeviceId, MacAddress>() { | 49 | + /** |
| 34 | - { | 50 | + * Constructor. Reads all the configuration for all devices of type |
| 35 | - put(DeviceId.deviceId("of:0000000000000001"), | 51 | + * Segment Router and organizes into various maps for easier access. |
| 36 | - MacAddress.valueOf("00:00:00:00:00:01")); | 52 | + * |
| 37 | - put(DeviceId.deviceId("of:0000000000000002"), | 53 | + * @param configService handle to network configuration manager |
| 38 | - MacAddress.valueOf("00:00:00:00:00:02")); | 54 | + * component from where the relevant configuration is retrieved. |
| 39 | - put(DeviceId.deviceId("of:0000000000000003"), | 55 | + */ |
| 40 | - MacAddress.valueOf("00:00:00:00:00:03")); | 56 | + public DeviceConfiguration(NetworkConfigManager configService) { |
| 41 | - put(DeviceId.deviceId("of:0000000000000004"), | 57 | + this.configService = checkNotNull(configService); |
| 42 | - MacAddress.valueOf("00:00:00:00:00:04")); | 58 | + List<SwitchConfig> allSwitchCfg = |
| 43 | - put(DeviceId.deviceId("of:0000000000000005"), | 59 | + this.configService.getConfiguredAllowedSwitches(); |
| 44 | - MacAddress.valueOf("00:00:00:00:00:05")); | 60 | + for (SwitchConfig cfg : allSwitchCfg) { |
| 45 | - put(DeviceId.deviceId("of:0000000000000006"), | 61 | + if (!(cfg instanceof SegmentRouterConfig)) { |
| 46 | - MacAddress.valueOf("00:00:00:00:00:06")); | 62 | + continue; |
| 47 | - } | 63 | + } |
| 48 | - }; | 64 | + SegmentRouterInfo info = new SegmentRouterInfo(); |
| 49 | - | 65 | + info.nodeSid = ((SegmentRouterConfig) cfg).getNodeSid(); |
| 50 | - private final HashMap<DeviceId, Ip4Address> deviceIpMap = | 66 | + info.deviceId = ((SegmentRouterConfig) cfg).getDpid(); |
| 51 | - new HashMap<DeviceId, Ip4Address>() { | 67 | + info.mac = MacAddress.valueOf((( |
| 52 | - { | 68 | + SegmentRouterConfig) cfg).getRouterMac()); |
| 53 | - put(DeviceId.deviceId("of:0000000000000001"), | 69 | + String routerIp = ((SegmentRouterConfig) cfg).getRouterIp(); |
| 54 | - Ip4Address.valueOf("192.168.0.1")); | 70 | + Ip4Prefix prefix = checkNotNull(IpPrefix.valueOf(routerIp).getIp4Prefix()); |
| 55 | - put(DeviceId.deviceId("of:0000000000000002"), | 71 | + info.ip = prefix.address(); |
| 56 | - Ip4Address.valueOf("192.168.0.2")); | 72 | + info.isEdge = ((SegmentRouterConfig) cfg).isEdgeRouter(); |
| 57 | - put(DeviceId.deviceId("of:0000000000000003"), | 73 | + info.subnets = new HashMap<>(); |
| 58 | - Ip4Address.valueOf("192.168.0.3")); | 74 | + info.gatewayIps = new HashMap<PortNumber, Ip4Address>(); |
| 59 | - put(DeviceId.deviceId("of:0000000000000004"), | 75 | + for (Subnet s: ((SegmentRouterConfig) cfg).getSubnets()) { |
| 60 | - Ip4Address.valueOf("192.168.0.4")); | 76 | + info.subnets.put(PortNumber.portNumber(s.getPortNo()), |
| 61 | - put(DeviceId.deviceId("of:0000000000000005"), | 77 | + Ip4Prefix.valueOf(s.getSubnetIp())); |
| 62 | - Ip4Address.valueOf("192.168.0.5")); | 78 | + String gatewayIp = s.getSubnetIp(). |
| 63 | - put(DeviceId.deviceId("of:0000000000000006"), | 79 | + substring(0, s.getSubnetIp().indexOf('/')); |
| 64 | - Ip4Address.valueOf("192.168.0.6")); | 80 | + info.gatewayIps.put(PortNumber.portNumber(s.getPortNo()), |
| 65 | - } | 81 | + Ip4Address.valueOf(gatewayIp)); |
| 66 | - }; | 82 | + } |
| 83 | + this.deviceConfigMap.put(info.deviceId, info); | ||
| 84 | + this.allSegmentIds.add(info.nodeSid); | ||
| 85 | + } | ||
| 86 | + } | ||
| 67 | 87 | ||
| 88 | + /** | ||
| 89 | + * Returns the segment id of a segment router. | ||
| 90 | + * | ||
| 91 | + * @param deviceId device identifier | ||
| 92 | + * @return segment id | ||
| 93 | + */ | ||
| 68 | @Override | 94 | @Override |
| 69 | public int getSegmentId(DeviceId deviceId) { | 95 | public int getSegmentId(DeviceId deviceId) { |
| 70 | - if (deviceSegmentIdMap.get(deviceId) != null) { | 96 | + if (deviceConfigMap.get(deviceId) != null) { |
| 71 | log.debug("getSegmentId for device{} is {}", | 97 | log.debug("getSegmentId for device{} is {}", |
| 72 | deviceId, | 98 | deviceId, |
| 73 | - deviceSegmentIdMap.get(deviceId)); | 99 | + deviceConfigMap.get(deviceId).nodeSid); |
| 74 | - return deviceSegmentIdMap.get(deviceId); | 100 | + return deviceConfigMap.get(deviceId).nodeSid; |
| 75 | } else { | 101 | } else { |
| 76 | throw new IllegalStateException(); | 102 | throw new IllegalStateException(); |
| 77 | } | 103 | } |
| 78 | } | 104 | } |
| 79 | 105 | ||
| 106 | + /** | ||
| 107 | + * Returns the segment id of a segment router given its mac address. | ||
| 108 | + * | ||
| 109 | + * @param routerMac router mac address | ||
| 110 | + * @return segment id | ||
| 111 | + */ | ||
| 112 | + public int getSegmentId(MacAddress routerMac) { | ||
| 113 | + for (Map.Entry<DeviceId, SegmentRouterInfo> entry: | ||
| 114 | + deviceConfigMap.entrySet()) { | ||
| 115 | + if (entry.getValue().mac.equals(routerMac)) { | ||
| 116 | + return entry.getValue().nodeSid; | ||
| 117 | + } | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + return -1; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + /** | ||
| 124 | + * Returns the segment id of a segment router given its router ip address. | ||
| 125 | + * | ||
| 126 | + * @param routerAddress router ip address | ||
| 127 | + * @return segment id | ||
| 128 | + */ | ||
| 129 | + public int getSegmentId(Ip4Address routerAddress) { | ||
| 130 | + for (Map.Entry<DeviceId, SegmentRouterInfo> entry: | ||
| 131 | + deviceConfigMap.entrySet()) { | ||
| 132 | + if (entry.getValue().ip.equals(routerAddress)) { | ||
| 133 | + return entry.getValue().nodeSid; | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + return -1; | ||
| 138 | + } | ||
| 80 | 139 | ||
| 140 | + /** | ||
| 141 | + * Returns the router mac of a segment router. | ||
| 142 | + * | ||
| 143 | + * @param deviceId device identifier | ||
| 144 | + * @return router mac address | ||
| 145 | + */ | ||
| 81 | @Override | 146 | @Override |
| 82 | public MacAddress getDeviceMac(DeviceId deviceId) { | 147 | public MacAddress getDeviceMac(DeviceId deviceId) { |
| 83 | - if (deviceMacMap.get(deviceId) != null) { | 148 | + if (deviceConfigMap.get(deviceId) != null) { |
| 84 | log.debug("getDeviceMac for device{} is {}", | 149 | log.debug("getDeviceMac for device{} is {}", |
| 85 | deviceId, | 150 | deviceId, |
| 86 | - deviceMacMap.get(deviceId)); | 151 | + deviceConfigMap.get(deviceId).mac); |
| 87 | - return deviceMacMap.get(deviceId); | 152 | + return deviceConfigMap.get(deviceId).mac; |
| 88 | } else { | 153 | } else { |
| 89 | throw new IllegalStateException(); | 154 | throw new IllegalStateException(); |
| 90 | } | 155 | } |
| 91 | } | 156 | } |
| 92 | 157 | ||
| 158 | + /** | ||
| 159 | + * Returns the router ip address of a segment router. | ||
| 160 | + * | ||
| 161 | + * @param deviceId device identifier | ||
| 162 | + * @return router ip address | ||
| 163 | + */ | ||
| 164 | + public Ip4Address getRouterIp(DeviceId deviceId) { | ||
| 165 | + if (deviceConfigMap.get(deviceId) != null) { | ||
| 166 | + log.debug("getDeviceIp for device{} is {}", | ||
| 167 | + deviceId, | ||
| 168 | + deviceConfigMap.get(deviceId).ip); | ||
| 169 | + return deviceConfigMap.get(deviceId).ip; | ||
| 170 | + } else { | ||
| 171 | + throw new IllegalStateException(); | ||
| 172 | + } | ||
| 173 | + } | ||
| 93 | 174 | ||
| 175 | + /** | ||
| 176 | + * Indicates if the segment router is a edge router or | ||
| 177 | + * a transit/back bone router. | ||
| 178 | + * | ||
| 179 | + * @param deviceId device identifier | ||
| 180 | + * @return boolean | ||
| 181 | + */ | ||
| 94 | @Override | 182 | @Override |
| 95 | public boolean isEdgeDevice(DeviceId deviceId) { | 183 | public boolean isEdgeDevice(DeviceId deviceId) { |
| 96 | - if (deviceId.equals(DeviceId.deviceId("of:0000000000000001")) | 184 | + if (deviceConfigMap.get(deviceId) != null) { |
| 97 | - || deviceId.equals(DeviceId.deviceId("of:0000000000000006"))) { | 185 | + log.debug("isEdgeDevice for device{} is {}", |
| 98 | - return true; | 186 | + deviceId, |
| 187 | + deviceConfigMap.get(deviceId).isEdge); | ||
| 188 | + return deviceConfigMap.get(deviceId).isEdge; | ||
| 189 | + } else { | ||
| 190 | + throw new IllegalStateException(); | ||
| 99 | } | 191 | } |
| 100 | - | ||
| 101 | - return false; | ||
| 102 | } | 192 | } |
| 103 | 193 | ||
| 194 | + /** | ||
| 195 | + * Returns the segment ids of all configured segment routers. | ||
| 196 | + * | ||
| 197 | + * @return list of segment ids | ||
| 198 | + */ | ||
| 104 | @Override | 199 | @Override |
| 105 | public List<Integer> getAllDeviceSegmentIds() { | 200 | public List<Integer> getAllDeviceSegmentIds() { |
| 106 | return allSegmentIds; | 201 | return allSegmentIds; |
| 107 | } | 202 | } |
| 108 | 203 | ||
| 109 | - | ||
| 110 | /** | 204 | /** |
| 111 | - * Returns Segment ID for the router with the MAC address given. | 205 | + * Returns the device identifier or data plane identifier (dpid) |
| 206 | + * of a segment router given its segment id. | ||
| 112 | * | 207 | * |
| 113 | - * @param targetMac Mac address for the router | 208 | + * @param sid segment id |
| 114 | - * @return Segment ID for the router with the MAC address | 209 | + * @return deviceId device identifier |
| 115 | */ | 210 | */ |
| 116 | - public int getSegmentId(MacAddress targetMac) { | 211 | + public DeviceId getDeviceId(int sid) { |
| 117 | - for (Map.Entry<DeviceId, MacAddress> entry: deviceMacMap.entrySet()) { | 212 | + for (Map.Entry<DeviceId, SegmentRouterInfo> entry: |
| 118 | - if (entry.getValue().equals(targetMac)) { | 213 | + deviceConfigMap.entrySet()) { |
| 119 | - return deviceSegmentIdMap.get(entry.getKey()); | 214 | + if (entry.getValue().nodeSid == sid) { |
| 215 | + return entry.getValue().deviceId; | ||
| 120 | } | 216 | } |
| 121 | } | 217 | } |
| 122 | 218 | ||
| 123 | - return -1; | 219 | + return null; |
| 124 | } | 220 | } |
| 125 | 221 | ||
| 126 | /** | 222 | /** |
| 127 | - * Returns Segment ID for the router withe IP address given. | 223 | + * Returns the device identifier or data plane identifier (dpid) |
| 224 | + * of a segment router given its router ip address. | ||
| 128 | * | 225 | * |
| 129 | - * @param targetAddress IP address of the router | 226 | + * @param ipAddress router ip address |
| 130 | - * @return Segment ID for the router with the IP address | 227 | + * @return deviceId device identifier |
| 131 | */ | 228 | */ |
| 132 | - public int getSegmentId(Ip4Address targetAddress) { | 229 | + public DeviceId getDeviceId(Ip4Address ipAddress) { |
| 133 | - for (Map.Entry<DeviceId, Ip4Address> entry: deviceIpMap.entrySet()) { | 230 | + for (Map.Entry<DeviceId, SegmentRouterInfo> entry: |
| 134 | - if (entry.getValue().equals(targetAddress)) { | 231 | + deviceConfigMap.entrySet()) { |
| 135 | - return deviceSegmentIdMap.get(entry.getKey()); | 232 | + if (entry.getValue().ip.equals(ipAddress)) { |
| 233 | + return entry.getValue().deviceId; | ||
| 136 | } | 234 | } |
| 137 | } | 235 | } |
| 138 | 236 | ||
| 139 | - return -1; | 237 | + return null; |
| 140 | } | 238 | } |
| 141 | 239 | ||
| 142 | /** | 240 | /** |
| 143 | - * Returns Router IP address for the router with the device ID given. | 241 | + * Returns the configured subnet gateway ip addresses for a segment router. |
| 144 | * | 242 | * |
| 145 | - * @param deviceId device ID of the router | 243 | + * @param deviceId device identifier |
| 146 | - * @return IP address of the router | 244 | + * @return list of ip addresses |
| 147 | */ | 245 | */ |
| 148 | - public Ip4Address getRouterIp(DeviceId deviceId) { | 246 | + public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) { |
| 149 | - if (deviceIpMap.get(deviceId) != null) { | 247 | + if (deviceConfigMap.get(deviceId) != null) { |
| 150 | - log.debug("getDeviceIp for device{} is {}", | 248 | + log.debug("getSubnetGatewayIps for device{} is {}", |
| 151 | deviceId, | 249 | deviceId, |
| 152 | - deviceIpMap.get(deviceId)); | 250 | + deviceConfigMap.get(deviceId).gatewayIps.values()); |
| 153 | - return deviceIpMap.get(deviceId); | 251 | + return new ArrayList<Ip4Address>(deviceConfigMap. |
| 252 | + get(deviceId).gatewayIps.values()); | ||
| 154 | } else { | 253 | } else { |
| 155 | - throw new IllegalStateException(); | 254 | + return null; |
| 156 | } | 255 | } |
| 157 | } | 256 | } |
| 158 | 257 | ||
| 159 | /** | 258 | /** |
| 160 | - * Returns the Device ID of the router with the Segment ID given. | 259 | + * Returns the configured subnet prefixes for a segment router. |
| 161 | * | 260 | * |
| 162 | - * @param sid Segment ID of the router | 261 | + * @param deviceId device identifier |
| 163 | - * @return Device ID of the router | 262 | + * @return list of ip prefixes |
| 164 | */ | 263 | */ |
| 165 | - public DeviceId getDeviceId(int sid) { | 264 | + public List<Ip4Prefix> getSubnets(DeviceId deviceId) { |
| 166 | - for (Map.Entry<DeviceId, Integer> entry: deviceSegmentIdMap.entrySet()) { | 265 | + if (deviceConfigMap.get(deviceId) != null) { |
| 167 | - if (entry.getValue() == sid) { | 266 | + log.debug("getSubnets for device{} is {}", |
| 168 | - return entry.getKey(); | 267 | + deviceId, |
| 268 | + deviceConfigMap.get(deviceId).subnets.values()); | ||
| 269 | + return new ArrayList<Ip4Prefix>(deviceConfigMap. | ||
| 270 | + get(deviceId).subnets.values()); | ||
| 271 | + } else { | ||
| 272 | + return null; | ||
| 169 | } | 273 | } |
| 170 | } | 274 | } |
| 171 | 275 | ||
| 276 | + /** | ||
| 277 | + * Returns the router ip address of segment router that has the | ||
| 278 | + * specified ip address in its subnets. | ||
| 279 | + * | ||
| 280 | + * @param destIpAddress target ip address | ||
| 281 | + * @return router ip address | ||
| 282 | + */ | ||
| 283 | + public Ip4Address getRouterIpAddressForASubnetHost(Ip4Address destIpAddress) { | ||
| 284 | + for (Map.Entry<DeviceId, SegmentRouterInfo> entry: | ||
| 285 | + deviceConfigMap.entrySet()) { | ||
| 286 | + for (Ip4Prefix prefix:entry.getValue().subnets.values()) { | ||
| 287 | + if (prefix.contains(destIpAddress)) { | ||
| 288 | + return entry.getValue().ip; | ||
| 289 | + } | ||
| 290 | + } | ||
| 291 | + } | ||
| 292 | + | ||
| 293 | + log.debug("No router was found for {}", destIpAddress); | ||
| 172 | return null; | 294 | return null; |
| 173 | } | 295 | } |
| 174 | 296 | ||
| 175 | /** | 297 | /** |
| 176 | - * Returns the Device ID of the router with the IP address given. | 298 | + * Returns the router mac address of segment router that has the |
| 299 | + * specified ip address as one of its subnet gateway ip address. | ||
| 177 | * | 300 | * |
| 178 | - * @param ipAddress IP address of the router | 301 | + * @param gatewayIpAddress router gateway ip address |
| 179 | - * @return Device ID of the router | 302 | + * @return router mac address |
| 180 | */ | 303 | */ |
| 181 | - public DeviceId getDeviceId(Ip4Address ipAddress) { | 304 | + public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) { |
| 182 | - for (Map.Entry<DeviceId, Ip4Address> entry: deviceIpMap.entrySet()) { | 305 | + for (Map.Entry<DeviceId, SegmentRouterInfo> entry: |
| 183 | - if (entry.getValue().equals(ipAddress)) { | 306 | + deviceConfigMap.entrySet()) { |
| 184 | - return entry.getKey(); | 307 | + if (entry.getValue().gatewayIps. |
| 308 | + values().contains(gatewayIpAddress)) { | ||
| 309 | + return entry.getValue().mac; | ||
| 185 | } | 310 | } |
| 186 | } | 311 | } |
| 187 | 312 | ||
| 313 | + log.debug("Cannot find a router for {}", gatewayIpAddress); | ||
| 188 | return null; | 314 | return null; |
| 189 | } | 315 | } |
| 190 | } | 316 | } | ... | ... |
| ... | @@ -16,7 +16,7 @@ | ... | @@ -16,7 +16,7 @@ |
| 16 | package org.onosproject.segmentrouting; | 16 | package org.onosproject.segmentrouting; |
| 17 | 17 | ||
| 18 | import java.nio.ByteBuffer; | 18 | import java.nio.ByteBuffer; |
| 19 | - | 19 | +import java.util.List; |
| 20 | import org.onlab.packet.Ethernet; | 20 | import org.onlab.packet.Ethernet; |
| 21 | import org.onlab.packet.ICMP; | 21 | import org.onlab.packet.ICMP; |
| 22 | import org.onlab.packet.IPv4; | 22 | import org.onlab.packet.IPv4; |
| ... | @@ -69,14 +69,14 @@ public class IcmpHandler { | ... | @@ -69,14 +69,14 @@ public class IcmpHandler { |
| 69 | DeviceId deviceId = connectPoint.deviceId(); | 69 | DeviceId deviceId = connectPoint.deviceId(); |
| 70 | Ip4Address destinationAddress = | 70 | Ip4Address destinationAddress = |
| 71 | Ip4Address.valueOf(ipv4.getDestinationAddress()); | 71 | Ip4Address.valueOf(ipv4.getDestinationAddress()); |
| 72 | - Ip4Address gatewayIpAddress = config.getGatewayIpAddress(deviceId); | 72 | + List<Ip4Address> gatewayIpAddresses = config.getGatewayIpAddress(deviceId); |
| 73 | IpPrefix routerIpPrefix = config.getRouterIpAddress(deviceId); | 73 | IpPrefix routerIpPrefix = config.getRouterIpAddress(deviceId); |
| 74 | Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address(); | 74 | Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address(); |
| 75 | 75 | ||
| 76 | // ICMP to the router IP or gateway IP | 76 | // ICMP to the router IP or gateway IP |
| 77 | if (((ICMP) ipv4.getPayload()).getIcmpType() == ICMP.TYPE_ECHO_REQUEST && | 77 | if (((ICMP) ipv4.getPayload()).getIcmpType() == ICMP.TYPE_ECHO_REQUEST && |
| 78 | (destinationAddress.equals(routerIpAddress) || | 78 | (destinationAddress.equals(routerIpAddress) || |
| 79 | - gatewayIpAddress.equals(destinationAddress))) { | 79 | + gatewayIpAddresses.contains(destinationAddress))) { |
| 80 | sendICMPResponse(ethernet, connectPoint); | 80 | sendICMPResponse(ethernet, connectPoint); |
| 81 | // TODO: do we need to set the flow rule again ?? | 81 | // TODO: do we need to set the flow rule again ?? |
| 82 | 82 | ... | ... |
| ... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
| 16 | package org.onosproject.segmentrouting; | 16 | package org.onosproject.segmentrouting; |
| 17 | 17 | ||
| 18 | import com.google.common.collect.Lists; | 18 | import com.google.common.collect.Lists; |
| 19 | + | ||
| 19 | import org.onlab.packet.Ip4Address; | 20 | import org.onlab.packet.Ip4Address; |
| 20 | import org.onlab.packet.Ip4Prefix; | 21 | import org.onlab.packet.Ip4Prefix; |
| 21 | import org.onlab.packet.IpPrefix; | 22 | import org.onlab.packet.IpPrefix; |
| ... | @@ -26,39 +27,33 @@ import org.onosproject.net.PortNumber; | ... | @@ -26,39 +27,33 @@ import org.onosproject.net.PortNumber; |
| 26 | import org.slf4j.Logger; | 27 | import org.slf4j.Logger; |
| 27 | import org.slf4j.LoggerFactory; | 28 | import org.slf4j.LoggerFactory; |
| 28 | 29 | ||
| 29 | -import java.net.URI; | ||
| 30 | import java.util.List; | 30 | import java.util.List; |
| 31 | import java.util.Set; | 31 | import java.util.Set; |
| 32 | 32 | ||
| 33 | /** | 33 | /** |
| 34 | * This class is temporary class and used only for test. | 34 | * This class is temporary class and used only for test. |
| 35 | * It will be replaced with "real" Network Config Manager. | 35 | * It will be replaced with "real" Network Config Manager. |
| 36 | + * | ||
| 37 | + * TODO: Knock off this wrapper and directly use DeviceConfiguration class | ||
| 36 | */ | 38 | */ |
| 37 | 39 | ||
| 38 | public class NetworkConfigHandler { | 40 | public class NetworkConfigHandler { |
| 39 | 41 | ||
| 40 | private static Logger log = LoggerFactory.getLogger(NetworkConfigHandler.class); | 42 | private static Logger log = LoggerFactory.getLogger(NetworkConfigHandler.class); |
| 41 | private SegmentRoutingManager srManager; | 43 | private SegmentRoutingManager srManager; |
| 42 | - private DeviceConfiguration deviceConfig = new DeviceConfiguration(); | 44 | + private DeviceConfiguration deviceConfig; |
| 43 | 45 | ||
| 44 | - public NetworkConfigHandler(SegmentRoutingManager srManager) { | 46 | + public NetworkConfigHandler(SegmentRoutingManager srManager, |
| 47 | + DeviceConfiguration deviceConfig) { | ||
| 45 | this.srManager = srManager; | 48 | this.srManager = srManager; |
| 49 | + this.deviceConfig = deviceConfig; | ||
| 46 | } | 50 | } |
| 47 | 51 | ||
| 48 | - public Ip4Address getGatewayIpAddress(DeviceId deviceId) { | 52 | + public List<Ip4Address> getGatewayIpAddress(DeviceId deviceId) { |
| 49 | - | 53 | + return this.deviceConfig.getSubnetGatewayIps(deviceId); |
| 50 | - if (deviceId.uri().equals(URI.create("of:0000000000000001"))) { | ||
| 51 | - return Ip4Address.valueOf("10.0.1.128"); | ||
| 52 | - } else if (deviceId.uri().equals(URI.create("of:0000000000000006"))) { | ||
| 53 | - return Ip4Address.valueOf("7.7.7.128"); | ||
| 54 | - } | ||
| 55 | - | ||
| 56 | - log.warn("No gateway Ip address was found for {}", deviceId); | ||
| 57 | - return Ip4Address.valueOf("0.0.0.0"); | ||
| 58 | } | 54 | } |
| 59 | 55 | ||
| 60 | public IpPrefix getRouterIpAddress(DeviceId deviceId) { | 56 | public IpPrefix getRouterIpAddress(DeviceId deviceId) { |
| 61 | - | ||
| 62 | return IpPrefix.valueOf(deviceConfig.getRouterIp(deviceId), 32); | 57 | return IpPrefix.valueOf(deviceConfig.getRouterIp(deviceId), 32); |
| 63 | } | 58 | } |
| 64 | 59 | ||
| ... | @@ -68,17 +63,13 @@ public class NetworkConfigHandler { | ... | @@ -68,17 +63,13 @@ public class NetworkConfigHandler { |
| 68 | 63 | ||
| 69 | public boolean inSameSubnet(DeviceId deviceId, Ip4Address destIp) { | 64 | public boolean inSameSubnet(DeviceId deviceId, Ip4Address destIp) { |
| 70 | 65 | ||
| 71 | - String subnetInfo = getSubnetInfo(deviceId); | 66 | + List<Ip4Prefix> subnets = getSubnetInfo(deviceId); |
| 72 | - if (subnetInfo == null) { | 67 | + if (subnets == null) { |
| 73 | return false; | 68 | return false; |
| 74 | } | 69 | } |
| 75 | 70 | ||
| 76 | - IpPrefix prefix = IpPrefix.valueOf(subnetInfo); | 71 | + return subnets.stream() |
| 77 | - if (prefix.contains(destIp)) { | 72 | + .anyMatch((subnet) -> subnet.contains(destIp)); |
| 78 | - return true; | ||
| 79 | - } | ||
| 80 | - | ||
| 81 | - return false; | ||
| 82 | } | 73 | } |
| 83 | 74 | ||
| 84 | public boolean inSameSubnet(Ip4Address address, int sid) { | 75 | public boolean inSameSubnet(Ip4Address address, int sid) { |
| ... | @@ -88,43 +79,23 @@ public class NetworkConfigHandler { | ... | @@ -88,43 +79,23 @@ public class NetworkConfigHandler { |
| 88 | return false; | 79 | return false; |
| 89 | } | 80 | } |
| 90 | 81 | ||
| 91 | - String subnetInfo = getSubnetInfo(deviceId); | 82 | + return inSameSubnet(deviceId, address); |
| 92 | - if (subnetInfo == null) { | ||
| 93 | - log.warn("Cannot find the subnet info for {}", deviceId); | ||
| 94 | - return false; | ||
| 95 | } | 83 | } |
| 96 | 84 | ||
| 97 | - Ip4Prefix subnet = Ip4Prefix.valueOf(subnetInfo); | 85 | + public List<Ip4Prefix> getSubnetInfo(DeviceId deviceId) { |
| 98 | - if (subnet.contains(address)) { | 86 | + return deviceConfig.getSubnets(deviceId); |
| 99 | - return true; | ||
| 100 | - } | ||
| 101 | - | ||
| 102 | - return false; | ||
| 103 | - | ||
| 104 | - } | ||
| 105 | - | ||
| 106 | - public String getSubnetInfo(DeviceId deviceId) { | ||
| 107 | - // TODO : supports multiple subnet | ||
| 108 | - if (deviceId.uri().equals(URI.create("of:0000000000000001"))) { | ||
| 109 | - return "10.0.1.1/24"; | ||
| 110 | - } else if (deviceId.uri().equals(URI.create("of:0000000000000006"))) { | ||
| 111 | - return "7.7.7.7/24"; | ||
| 112 | - } else { | ||
| 113 | - log.error("Switch {} is not an edge router", deviceId); | ||
| 114 | - return null; | ||
| 115 | - } | ||
| 116 | } | 87 | } |
| 117 | 88 | ||
| 118 | public int getMplsId(DeviceId deviceId) { | 89 | public int getMplsId(DeviceId deviceId) { |
| 119 | return deviceConfig.getSegmentId(deviceId); | 90 | return deviceConfig.getSegmentId(deviceId); |
| 120 | } | 91 | } |
| 121 | 92 | ||
| 122 | - public int getMplsId(MacAddress mac) { | 93 | + public int getMplsId(MacAddress routerMac) { |
| 123 | - return deviceConfig.getSegmentId(mac); | 94 | + return deviceConfig.getSegmentId(routerMac); |
| 124 | } | 95 | } |
| 125 | 96 | ||
| 126 | - public int getMplsId(Ip4Address address) { | 97 | + public int getMplsId(Ip4Address routerIpAddress) { |
| 127 | - return deviceConfig.getSegmentId(address); | 98 | + return deviceConfig.getSegmentId(routerIpAddress); |
| 128 | } | 99 | } |
| 129 | 100 | ||
| 130 | public boolean isEcmpNotSupportedInTransit(DeviceId deviceId) { | 101 | public boolean isEcmpNotSupportedInTransit(DeviceId deviceId) { |
| ... | @@ -132,17 +103,12 @@ public class NetworkConfigHandler { | ... | @@ -132,17 +103,12 @@ public class NetworkConfigHandler { |
| 132 | } | 103 | } |
| 133 | 104 | ||
| 134 | public boolean isTransitRouter(DeviceId deviceId) { | 105 | public boolean isTransitRouter(DeviceId deviceId) { |
| 135 | - return true; | 106 | + return !(deviceConfig.isEdgeDevice(deviceId)); |
| 136 | } | 107 | } |
| 137 | 108 | ||
| 138 | 109 | ||
| 139 | public boolean isEdgeRouter(DeviceId deviceId) { | 110 | public boolean isEdgeRouter(DeviceId deviceId) { |
| 140 | - if (deviceId.uri().equals(URI.create("of:0000000000000001")) | 111 | + return deviceConfig.isEdgeDevice(deviceId); |
| 141 | - || deviceId.uri().equals(URI.create("of:0000000000000006"))) { | ||
| 142 | - return true; | ||
| 143 | - } | ||
| 144 | - | ||
| 145 | - return false; | ||
| 146 | } | 112 | } |
| 147 | 113 | ||
| 148 | private List<PortNumber> getPortsToNeighbors(DeviceId deviceId, List<DeviceId> fwdSws) { | 114 | private List<PortNumber> getPortsToNeighbors(DeviceId deviceId, List<DeviceId> fwdSws) { |
| ... | @@ -177,16 +143,7 @@ public class NetworkConfigHandler { | ... | @@ -177,16 +143,7 @@ public class NetworkConfigHandler { |
| 177 | 143 | ||
| 178 | 144 | ||
| 179 | public Ip4Address getDestinationRouterAddress(Ip4Address destIpAddress) { | 145 | public Ip4Address getDestinationRouterAddress(Ip4Address destIpAddress) { |
| 180 | - // TODO: need to check the subnet info | 146 | + return deviceConfig.getRouterIpAddressForASubnetHost(destIpAddress); |
| 181 | - if (destIpAddress.toString().equals("10.0.1.1")) { | ||
| 182 | - return Ip4Address.valueOf("192.168.0.1"); | ||
| 183 | - } else if (destIpAddress.toString().equals("7.7.7.7")) { | ||
| 184 | - return Ip4Address.valueOf("192.168.0.6"); | ||
| 185 | - } else { | ||
| 186 | - log.warn("No router was found for {}", destIpAddress); | ||
| 187 | - return null; | ||
| 188 | - } | ||
| 189 | - | ||
| 190 | } | 147 | } |
| 191 | 148 | ||
| 192 | public DeviceId getDeviceId(Ip4Address ip4Address) { | 149 | public DeviceId getDeviceId(Ip4Address ip4Address) { |
| ... | @@ -194,13 +151,6 @@ public class NetworkConfigHandler { | ... | @@ -194,13 +151,6 @@ public class NetworkConfigHandler { |
| 194 | } | 151 | } |
| 195 | 152 | ||
| 196 | public MacAddress getRouterMac(Ip4Address targetAddress) { | 153 | public MacAddress getRouterMac(Ip4Address targetAddress) { |
| 197 | - if (targetAddress.toString().equals("10.0.1.128")) { | 154 | + return deviceConfig.getRouterMacForAGatewayIp(targetAddress); |
| 198 | - return MacAddress.valueOf("00:00:00:00:00:01"); | ||
| 199 | - } else if (targetAddress.toString().equals("7.7.7.128")) { | ||
| 200 | - return MacAddress.valueOf("00:00:00:00:00:06"); | ||
| 201 | - } else { | ||
| 202 | - log.warn("Cannot find a router for {}", targetAddress); | ||
| 203 | - return null; | ||
| 204 | - } | ||
| 205 | } | 155 | } |
| 206 | } | 156 | } | ... | ... |
| ... | @@ -17,11 +17,11 @@ package org.onosproject.segmentrouting; | ... | @@ -17,11 +17,11 @@ package org.onosproject.segmentrouting; |
| 17 | 17 | ||
| 18 | import org.onlab.packet.Ethernet; | 18 | import org.onlab.packet.Ethernet; |
| 19 | import org.onlab.packet.Ip4Address; | 19 | import org.onlab.packet.Ip4Address; |
| 20 | +import org.onlab.packet.Ip4Prefix; | ||
| 20 | import org.onlab.packet.IpPrefix; | 21 | import org.onlab.packet.IpPrefix; |
| 21 | import org.onlab.packet.MacAddress; | 22 | import org.onlab.packet.MacAddress; |
| 22 | - | ||
| 23 | import org.onlab.packet.MplsLabel; | 23 | import org.onlab.packet.MplsLabel; |
| 24 | -import org.onosproject.grouphandler.NeighborSet; | 24 | +import org.onosproject.segmentrouting.grouphandler.NeighborSet; |
| 25 | import org.onosproject.net.DeviceId; | 25 | import org.onosproject.net.DeviceId; |
| 26 | import org.onosproject.net.Link; | 26 | import org.onosproject.net.Link; |
| 27 | import org.onosproject.net.PortNumber; | 27 | import org.onosproject.net.PortNumber; |
| ... | @@ -94,15 +94,15 @@ public class RoutingRulePopulator { | ... | @@ -94,15 +94,15 @@ public class RoutingRulePopulator { |
| 94 | * Populates IP flow rules for the subnets of the destination router. | 94 | * Populates IP flow rules for the subnets of the destination router. |
| 95 | * | 95 | * |
| 96 | * @param deviceId switch ID to set the rules | 96 | * @param deviceId switch ID to set the rules |
| 97 | - * @param subnetInfo subnet information | 97 | + * @param subnets subnet information |
| 98 | * @param destSw destination switch ID | 98 | * @param destSw destination switch ID |
| 99 | * @param nextHops next hop switch ID list | 99 | * @param nextHops next hop switch ID list |
| 100 | * @return true if all rules are set successfully, false otherwise | 100 | * @return true if all rules are set successfully, false otherwise |
| 101 | */ | 101 | */ |
| 102 | - public boolean populateIpRuleForSubnet(DeviceId deviceId, String subnetInfo, | 102 | + public boolean populateIpRuleForSubnet(DeviceId deviceId, List<Ip4Prefix> subnets, |
| 103 | DeviceId destSw, Set<DeviceId> nextHops) { | 103 | DeviceId destSw, Set<DeviceId> nextHops) { |
| 104 | 104 | ||
| 105 | - List<IpPrefix> subnets = extractSubnet(subnetInfo); | 105 | + //List<IpPrefix> subnets = extractSubnet(subnetInfo); |
| 106 | for (IpPrefix subnet: subnets) { | 106 | for (IpPrefix subnet: subnets) { |
| 107 | if (!populateIpRuleForRouter(deviceId, subnet, destSw, nextHops)) { | 107 | if (!populateIpRuleForRouter(deviceId, subnet, destSw, nextHops)) { |
| 108 | return false; | 108 | return false; |
| ... | @@ -371,21 +371,6 @@ public class RoutingRulePopulator { | ... | @@ -371,21 +371,6 @@ public class RoutingRulePopulator { |
| 371 | 371 | ||
| 372 | } | 372 | } |
| 373 | 373 | ||
| 374 | - | ||
| 375 | - private List<IpPrefix> extractSubnet(String subnetInfo) { | ||
| 376 | - List<IpPrefix> subnetIpPrefixes = new ArrayList<>(); | ||
| 377 | - | ||
| 378 | - // TODO: refactoring required depending on the format of the subnet info | ||
| 379 | - IpPrefix prefix = IpPrefix.valueOf(subnetInfo); | ||
| 380 | - if (prefix == null) { | ||
| 381 | - log.error("Wrong ip prefix type {}", subnetInfo); | ||
| 382 | - } else { | ||
| 383 | - subnetIpPrefixes.add(prefix); | ||
| 384 | - } | ||
| 385 | - | ||
| 386 | - return subnetIpPrefixes; | ||
| 387 | - } | ||
| 388 | - | ||
| 389 | private Link selectOneLink(DeviceId srcId, Set<DeviceId> destIds) { | 374 | private Link selectOneLink(DeviceId srcId, Set<DeviceId> destIds) { |
| 390 | 375 | ||
| 391 | Set<Link> links = srManager.linkService.getDeviceEgressLinks(srcId); | 376 | Set<Link> links = srManager.linkService.getDeviceEgressLinks(srcId); | ... | ... |
| ... | @@ -25,8 +25,8 @@ import org.onlab.packet.IPv4; | ... | @@ -25,8 +25,8 @@ import org.onlab.packet.IPv4; |
| 25 | import org.onosproject.core.ApplicationId; | 25 | import org.onosproject.core.ApplicationId; |
| 26 | import org.onosproject.core.CoreService; | 26 | import org.onosproject.core.CoreService; |
| 27 | import org.onosproject.event.Event; | 27 | import org.onosproject.event.Event; |
| 28 | -import org.onosproject.grouphandler.DefaultGroupHandler; | 28 | +import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler; |
| 29 | -import org.onosproject.grouphandler.NeighborSet; | 29 | +import org.onosproject.segmentrouting.grouphandler.NeighborSet; |
| 30 | import org.onosproject.mastership.MastershipService; | 30 | import org.onosproject.mastership.MastershipService; |
| 31 | import org.onosproject.net.Device; | 31 | import org.onosproject.net.Device; |
| 32 | import org.onosproject.net.DeviceId; | 32 | import org.onosproject.net.DeviceId; |
| ... | @@ -52,6 +52,7 @@ import org.onosproject.net.packet.PacketContext; | ... | @@ -52,6 +52,7 @@ import org.onosproject.net.packet.PacketContext; |
| 52 | import org.onosproject.net.packet.PacketProcessor; | 52 | import org.onosproject.net.packet.PacketProcessor; |
| 53 | import org.onosproject.net.packet.PacketService; | 53 | import org.onosproject.net.packet.PacketService; |
| 54 | import org.onosproject.net.topology.TopologyService; | 54 | import org.onosproject.net.topology.TopologyService; |
| 55 | +import org.onosproject.segmentrouting.config.NetworkConfigManager; | ||
| 55 | import org.slf4j.Logger; | 56 | import org.slf4j.Logger; |
| 56 | import org.slf4j.LoggerFactory; | 57 | import org.slf4j.LoggerFactory; |
| 57 | 58 | ||
| ... | @@ -98,16 +99,15 @@ public class SegmentRoutingManager { | ... | @@ -98,16 +99,15 @@ public class SegmentRoutingManager { |
| 98 | 99 | ||
| 99 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 100 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 100 | protected MastershipService mastershipService; | 101 | protected MastershipService mastershipService; |
| 101 | - | 102 | + protected NetworkConfigHandler networkConfigHandler = null; |
| 102 | - protected NetworkConfigHandler networkConfigHandler = new NetworkConfigHandler(this); | 103 | + protected ArpHandler arpHandler = null; |
| 103 | - protected ArpHandler arpHandler = new ArpHandler(this); | 104 | + protected IcmpHandler icmpHandler = null; |
| 104 | - protected IcmpHandler icmpHandler = new IcmpHandler(this); | 105 | + protected IpHandler ipHandler = null; |
| 105 | - protected IpHandler ipHandler = new IpHandler(this); | 106 | + protected RoutingRulePopulator routingRulePopulator = null; |
| 106 | - protected RoutingRulePopulator routingRulePopulator = new RoutingRulePopulator(this); | ||
| 107 | protected ApplicationId appId; | 107 | protected ApplicationId appId; |
| 108 | 108 | ||
| 109 | - private DefaultRoutingHandler defaultRoutingHandler = new DefaultRoutingHandler(this); | 109 | + private DefaultRoutingHandler defaultRoutingHandler = null; |
| 110 | - private DeviceConfiguration deviceConfiguration = new DeviceConfiguration(); | 110 | + private DeviceConfiguration deviceConfiguration = null; |
| 111 | private InternalPacketProcessor processor = new InternalPacketProcessor(); | 111 | private InternalPacketProcessor processor = new InternalPacketProcessor(); |
| 112 | private InternalEventHandler eventHandler = new InternalEventHandler(); | 112 | private InternalEventHandler eventHandler = new InternalEventHandler(); |
| 113 | 113 | ||
| ... | @@ -118,6 +118,8 @@ public class SegmentRoutingManager { | ... | @@ -118,6 +118,8 @@ public class SegmentRoutingManager { |
| 118 | private Map<DeviceId, DefaultGroupHandler> groupHandlerMap | 118 | private Map<DeviceId, DefaultGroupHandler> groupHandlerMap |
| 119 | = new ConcurrentHashMap<DeviceId, DefaultGroupHandler>(); | 119 | = new ConcurrentHashMap<DeviceId, DefaultGroupHandler>(); |
| 120 | 120 | ||
| 121 | + private NetworkConfigManager networkConfigService = new NetworkConfigManager();; | ||
| 122 | + | ||
| 121 | private static int numOfEvents = 0; | 123 | private static int numOfEvents = 0; |
| 122 | private static int numOfHandlerExecution = 0; | 124 | private static int numOfHandlerExecution = 0; |
| 123 | private static int numOfHandlerScheduled = 0; | 125 | private static int numOfHandlerScheduled = 0; |
| ... | @@ -125,6 +127,16 @@ public class SegmentRoutingManager { | ... | @@ -125,6 +127,16 @@ public class SegmentRoutingManager { |
| 125 | @Activate | 127 | @Activate |
| 126 | protected void activate() { | 128 | protected void activate() { |
| 127 | appId = coreService.registerApplication("org.onosproject.segmentrouting"); | 129 | appId = coreService.registerApplication("org.onosproject.segmentrouting"); |
| 130 | + networkConfigService.init(); | ||
| 131 | + deviceConfiguration = new DeviceConfiguration(networkConfigService); | ||
| 132 | + networkConfigHandler = new NetworkConfigHandler(this, | ||
| 133 | + deviceConfiguration); | ||
| 134 | + arpHandler = new ArpHandler(this); | ||
| 135 | + icmpHandler = new IcmpHandler(this); | ||
| 136 | + ipHandler = new IpHandler(this); | ||
| 137 | + routingRulePopulator = new RoutingRulePopulator(this); | ||
| 138 | + defaultRoutingHandler = new DefaultRoutingHandler(this); | ||
| 139 | + | ||
| 128 | packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2); | 140 | packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2); |
| 129 | linkService.addListener(new InternalLinkListener()); | 141 | linkService.addListener(new InternalLinkListener()); |
| 130 | groupService.addListener(new InternalGroupListener()); | 142 | groupService.addListener(new InternalGroupListener()); |
| ... | @@ -271,6 +283,7 @@ public class SegmentRoutingManager { | ... | @@ -271,6 +283,7 @@ public class SegmentRoutingManager { |
| 271 | 283 | ||
| 272 | private class InternalEventHandler implements Runnable { | 284 | private class InternalEventHandler implements Runnable { |
| 273 | 285 | ||
| 286 | + @Override | ||
| 274 | public void run() { | 287 | public void run() { |
| 275 | numOfHandlerExecution++; | 288 | numOfHandlerExecution++; |
| 276 | while (!eventQueue.isEmpty()) { | 289 | while (!eventQueue.isEmpty()) { |
| ... | @@ -326,7 +339,11 @@ public class SegmentRoutingManager { | ... | @@ -326,7 +339,11 @@ public class SegmentRoutingManager { |
| 326 | log.debug("A new device with ID {} was added", device.id()); | 339 | log.debug("A new device with ID {} was added", device.id()); |
| 327 | defaultRoutingHandler.populateTtpRules(device.id()); | 340 | defaultRoutingHandler.populateTtpRules(device.id()); |
| 328 | DefaultGroupHandler dgh = DefaultGroupHandler.createGroupHandler( | 341 | DefaultGroupHandler dgh = DefaultGroupHandler.createGroupHandler( |
| 329 | - device.id(), appId, new DeviceConfiguration(), linkService, groupService); | 342 | + device.id(), |
| 343 | + appId, | ||
| 344 | + deviceConfiguration, | ||
| 345 | + linkService, | ||
| 346 | + groupService); | ||
| 330 | dgh.createGroups(); | 347 | dgh.createGroups(); |
| 331 | groupHandlerMap.put(device.id(), dgh); | 348 | groupHandlerMap.put(device.id(), dgh); |
| 332 | } | 349 | } | ... | ... |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/NetworkConfig.java
0 → 100644
| 1 | +package org.onosproject.segmentrouting.config; | ||
| 2 | + | ||
| 3 | +import java.util.ArrayList; | ||
| 4 | +import java.util.List; | ||
| 5 | +import java.util.Map; | ||
| 6 | + | ||
| 7 | +import org.onosproject.net.DeviceId; | ||
| 8 | +import org.slf4j.Logger; | ||
| 9 | +import org.slf4j.LoggerFactory; | ||
| 10 | + | ||
| 11 | +import com.fasterxml.jackson.annotation.JsonProperty; | ||
| 12 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * Public class corresponding to JSON described data model. Defines the network | ||
| 16 | + * configuration at startup. | ||
| 17 | + */ | ||
| 18 | +public class NetworkConfig { | ||
| 19 | + protected static final Logger log = LoggerFactory.getLogger(NetworkConfig.class); | ||
| 20 | + | ||
| 21 | + @SuppressWarnings("unused") | ||
| 22 | + private String comment; | ||
| 23 | + | ||
| 24 | + private Boolean restrictSwitches; | ||
| 25 | + private Boolean restrictLinks; | ||
| 26 | + private List<SwitchConfig> switches; | ||
| 27 | + private List<LinkConfig> links; | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * Default constructor. | ||
| 31 | + */ | ||
| 32 | + public NetworkConfig() { | ||
| 33 | + switches = new ArrayList<SwitchConfig>(); | ||
| 34 | + links = new ArrayList<LinkConfig>(); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + @JsonProperty("comment") | ||
| 38 | + public void setComment(String c) { | ||
| 39 | + log.trace("NetworkConfig: comment={}", c); | ||
| 40 | + comment = c; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + @JsonProperty("restrictSwitches") | ||
| 44 | + public void setRestrictSwitches(boolean rs) { | ||
| 45 | + log.trace("NetworkConfig: restrictSwitches={}", rs); | ||
| 46 | + restrictSwitches = rs; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * Returns default restrict configuration for switches. | ||
| 51 | + * | ||
| 52 | + * @return boolean | ||
| 53 | + */ | ||
| 54 | + public Boolean getRestrictSwitches() { | ||
| 55 | + return restrictSwitches; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + @JsonProperty("restrictLinks") | ||
| 59 | + public void setRestrictLinks(boolean rl) { | ||
| 60 | + log.trace("NetworkConfig: restrictLinks={}", rl); | ||
| 61 | + restrictLinks = rl; | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + /** | ||
| 65 | + * Returns default restrict configuration for links. | ||
| 66 | + * | ||
| 67 | + * @return boolean | ||
| 68 | + */ | ||
| 69 | + public Boolean getRestrictLinks() { | ||
| 70 | + return restrictLinks; | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * Returns configuration for switches. | ||
| 75 | + * | ||
| 76 | + * @return list of switch configuration | ||
| 77 | + */ | ||
| 78 | + public List<SwitchConfig> getSwitchConfig() { | ||
| 79 | + return switches; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + @JsonProperty("switchConfig") | ||
| 83 | + public void setSwitchConfig(List<SwitchConfig> switches2) { | ||
| 84 | + log.trace("NetworkConfig: switchConfig={}", switches2); | ||
| 85 | + this.switches = switches2; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + /** | ||
| 89 | + * Java class corresponding to JSON described switch | ||
| 90 | + * configuration data model. | ||
| 91 | + */ | ||
| 92 | + public static class SwitchConfig { | ||
| 93 | + protected String nodeDpid; | ||
| 94 | + protected String name; | ||
| 95 | + protected String type; | ||
| 96 | + protected boolean allowed; | ||
| 97 | + protected double latitude; | ||
| 98 | + protected double longitude; | ||
| 99 | + protected Map<String, JsonNode> params; | ||
| 100 | + protected Map<String, String> publishAttributes; | ||
| 101 | + protected DeviceId dpid; | ||
| 102 | + | ||
| 103 | + /** | ||
| 104 | + * Returns the configured "name" of a switch. | ||
| 105 | + * | ||
| 106 | + * @return string | ||
| 107 | + */ | ||
| 108 | + public String getName() { | ||
| 109 | + return name; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + @JsonProperty("name") | ||
| 113 | + public void setName(String name) { | ||
| 114 | + log.trace("SwitchConfig: name={}", name); | ||
| 115 | + this.name = name; | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + /** | ||
| 119 | + * Returns the data plane identifier of a switch. | ||
| 120 | + * | ||
| 121 | + * @return ONOS device identifier | ||
| 122 | + */ | ||
| 123 | + public DeviceId getDpid() { | ||
| 124 | + return dpid; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + public void setDpid(DeviceId dpid) { | ||
| 128 | + this.dpid = dpid; | ||
| 129 | + this.nodeDpid = dpid.toString(); | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + /** | ||
| 133 | + * Returns the data plane identifier of a switch. | ||
| 134 | + * | ||
| 135 | + * @return string | ||
| 136 | + */ | ||
| 137 | + public String getNodeDpid() { | ||
| 138 | + return nodeDpid; | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + // mapper sets both DeviceId and string fields for dpid | ||
| 142 | + @JsonProperty("nodeDpid") | ||
| 143 | + public void setNodeDpid(String nodeDpid) { | ||
| 144 | + log.trace("SwitchConfig: nodeDpid={}", nodeDpid); | ||
| 145 | + this.nodeDpid = nodeDpid; | ||
| 146 | + this.dpid = DeviceId.deviceId(nodeDpid); | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + /** | ||
| 150 | + * Returns the type of a switch. | ||
| 151 | + * | ||
| 152 | + * @return string | ||
| 153 | + */ | ||
| 154 | + public String getType() { | ||
| 155 | + return type; | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + @JsonProperty("type") | ||
| 159 | + public void setType(String type) { | ||
| 160 | + log.trace("SwitchConfig: type={}", type); | ||
| 161 | + this.type = type; | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + /** | ||
| 165 | + * Returns the latitude of a switch. | ||
| 166 | + * | ||
| 167 | + * @return double | ||
| 168 | + */ | ||
| 169 | + public double getLatitude() { | ||
| 170 | + return latitude; | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + @JsonProperty("latitude") | ||
| 174 | + public void setLatitude(double latitude) { | ||
| 175 | + log.trace("SwitchConfig: latitude={}", latitude); | ||
| 176 | + this.latitude = latitude; | ||
| 177 | + } | ||
| 178 | + | ||
| 179 | + /** | ||
| 180 | + * Returns the longitude of a switch. | ||
| 181 | + * | ||
| 182 | + * @return double | ||
| 183 | + */ | ||
| 184 | + public double getLongitude() { | ||
| 185 | + return longitude; | ||
| 186 | + } | ||
| 187 | + | ||
| 188 | + @JsonProperty("longitude") | ||
| 189 | + public void setLongitude(double longitude) { | ||
| 190 | + log.trace("SwitchConfig: longitude={}", longitude); | ||
| 191 | + this.longitude = longitude; | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + /** | ||
| 195 | + * Returns the allowed flag for a switch. | ||
| 196 | + * | ||
| 197 | + * @return boolean | ||
| 198 | + */ | ||
| 199 | + public boolean isAllowed() { | ||
| 200 | + return allowed; | ||
| 201 | + } | ||
| 202 | + | ||
| 203 | + @JsonProperty("allowed") | ||
| 204 | + public void setAllowed(boolean allowed) { | ||
| 205 | + this.allowed = allowed; | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + /** | ||
| 209 | + * Returns the additional configured parameters of a switch. | ||
| 210 | + * | ||
| 211 | + * @return key value map | ||
| 212 | + */ | ||
| 213 | + public Map<String, JsonNode> getParams() { | ||
| 214 | + return params; | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + @JsonProperty("params") | ||
| 218 | + public void setParams(Map<String, JsonNode> params) { | ||
| 219 | + this.params = params; | ||
| 220 | + } | ||
| 221 | + | ||
| 222 | + /** | ||
| 223 | + * Reserved for future use. | ||
| 224 | + * | ||
| 225 | + * @return key value map | ||
| 226 | + */ | ||
| 227 | + public Map<String, String> getPublishAttributes() { | ||
| 228 | + return publishAttributes; | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | + @JsonProperty("publishAttributes") | ||
| 232 | + public void setPublishAttributes(Map<String, String> publishAttributes) { | ||
| 233 | + this.publishAttributes = publishAttributes; | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + } | ||
| 237 | + | ||
| 238 | + @JsonProperty("linkConfig") | ||
| 239 | + public void setLinkConfig(List<LinkConfig> links2) { | ||
| 240 | + this.links = links2; | ||
| 241 | + } | ||
| 242 | + | ||
| 243 | + /** | ||
| 244 | + * Reserved for future use. | ||
| 245 | + * | ||
| 246 | + * @return list of configured link configuration | ||
| 247 | + */ | ||
| 248 | + public List<LinkConfig> getLinkConfig() { | ||
| 249 | + return links; | ||
| 250 | + } | ||
| 251 | + | ||
| 252 | + /** | ||
| 253 | + * Reserved for future use. | ||
| 254 | + */ | ||
| 255 | + public static class LinkConfig { | ||
| 256 | + protected String type; | ||
| 257 | + protected Boolean allowed; | ||
| 258 | + protected DeviceId dpid1; | ||
| 259 | + protected DeviceId dpid2; | ||
| 260 | + protected String nodeDpid1; | ||
| 261 | + protected String nodeDpid2; | ||
| 262 | + protected Map<String, JsonNode> params; | ||
| 263 | + protected Map<String, String> publishAttributes; | ||
| 264 | + | ||
| 265 | + public String getType() { | ||
| 266 | + return type; | ||
| 267 | + } | ||
| 268 | + | ||
| 269 | + public void setType(String type) { | ||
| 270 | + this.type = type; | ||
| 271 | + } | ||
| 272 | + | ||
| 273 | + public Boolean isAllowed() { | ||
| 274 | + return allowed; | ||
| 275 | + } | ||
| 276 | + | ||
| 277 | + public void setAllowed(Boolean allowed) { | ||
| 278 | + this.allowed = allowed; | ||
| 279 | + } | ||
| 280 | + | ||
| 281 | + public String getNodeDpid1() { | ||
| 282 | + return nodeDpid1; | ||
| 283 | + } | ||
| 284 | + | ||
| 285 | + // mapper sets both long and string fields for dpid | ||
| 286 | + public void setNodeDpid1(String nodeDpid1) { | ||
| 287 | + this.nodeDpid1 = nodeDpid1; | ||
| 288 | + this.dpid1 = DeviceId.deviceId(nodeDpid1); | ||
| 289 | + } | ||
| 290 | + | ||
| 291 | + public String getNodeDpid2() { | ||
| 292 | + return nodeDpid2; | ||
| 293 | + } | ||
| 294 | + | ||
| 295 | + // mapper sets both long and string fields for dpid | ||
| 296 | + public void setNodeDpid2(String nodeDpid2) { | ||
| 297 | + this.nodeDpid2 = nodeDpid2; | ||
| 298 | + this.dpid2 = DeviceId.deviceId(nodeDpid2); | ||
| 299 | + } | ||
| 300 | + | ||
| 301 | + public DeviceId getDpid1() { | ||
| 302 | + return dpid1; | ||
| 303 | + } | ||
| 304 | + | ||
| 305 | + public void setDpid1(DeviceId dpid1) { | ||
| 306 | + this.dpid1 = dpid1; | ||
| 307 | + this.nodeDpid1 = dpid1.toString(); | ||
| 308 | + } | ||
| 309 | + | ||
| 310 | + public DeviceId getDpid2() { | ||
| 311 | + return dpid2; | ||
| 312 | + } | ||
| 313 | + | ||
| 314 | + public void setDpid2(DeviceId dpid2) { | ||
| 315 | + this.dpid2 = dpid2; | ||
| 316 | + this.nodeDpid2 = dpid2.toString(); | ||
| 317 | + } | ||
| 318 | + | ||
| 319 | + public Map<String, JsonNode> getParams() { | ||
| 320 | + return params; | ||
| 321 | + } | ||
| 322 | + | ||
| 323 | + public void setParams(Map<String, JsonNode> params) { | ||
| 324 | + this.params = params; | ||
| 325 | + } | ||
| 326 | + | ||
| 327 | + public Map<String, String> getPublishAttributes() { | ||
| 328 | + return publishAttributes; | ||
| 329 | + } | ||
| 330 | + | ||
| 331 | + public void setPublishAttributes(Map<String, String> publishAttributes) { | ||
| 332 | + this.publishAttributes = publishAttributes; | ||
| 333 | + } | ||
| 334 | + } | ||
| 335 | +} | ||
| 336 | + |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/NetworkConfigException.java
0 → 100644
| 1 | +package org.onosproject.segmentrouting.config; | ||
| 2 | + | ||
| 3 | +import org.onosproject.net.DeviceId; | ||
| 4 | +import org.slf4j.Logger; | ||
| 5 | +import org.slf4j.LoggerFactory; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * NetworkConfigExceptions specifies a set of unchecked runtime exceptions that | ||
| 9 | + * can be thrown by the {@link NetworkConfigManager}. It indicates errors that | ||
| 10 | + * must be fixed in the config file before controller execution can proceed. | ||
| 11 | + */ | ||
| 12 | +public class NetworkConfigException extends RuntimeException { | ||
| 13 | + | ||
| 14 | + private static final long serialVersionUID = 4959684709803000652L; | ||
| 15 | + protected static final Logger log = LoggerFactory | ||
| 16 | + .getLogger(NetworkConfigException.class); | ||
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * Exception for duplicate device identifier configuration. | ||
| 20 | + */ | ||
| 21 | + public static class DuplicateDpid extends RuntimeException { | ||
| 22 | + private static final long serialVersionUID = 5491113234592145335L; | ||
| 23 | + | ||
| 24 | + public DuplicateDpid(DeviceId dpid) { | ||
| 25 | + super(); | ||
| 26 | + log.error("Duplicate dpid found in switch-config Dpid:{}", | ||
| 27 | + dpid); | ||
| 28 | + } | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * Exception for duplicate device name configuration. | ||
| 33 | + */ | ||
| 34 | + public static class DuplicateName extends RuntimeException { | ||
| 35 | + private static final long serialVersionUID = -4090171438031376129L; | ||
| 36 | + | ||
| 37 | + public DuplicateName(String name) { | ||
| 38 | + super(); | ||
| 39 | + log.error("Duplicate name found in switch-config name:{}", name); | ||
| 40 | + } | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + /** | ||
| 44 | + * Exception for unspecified device identifier for a switch. | ||
| 45 | + */ | ||
| 46 | + public static class DpidNotSpecified extends RuntimeException { | ||
| 47 | + private static final long serialVersionUID = -8494418855597117254L; | ||
| 48 | + | ||
| 49 | + public DpidNotSpecified(String name) { | ||
| 50 | + super(); | ||
| 51 | + log.error("Dpid not specified for switch-config name:{}", name); | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * Exception for unspecified device name for a switch. | ||
| 57 | + */ | ||
| 58 | + public static class NameNotSpecified extends RuntimeException { | ||
| 59 | + private static final long serialVersionUID = -3518881744110422891L; | ||
| 60 | + | ||
| 61 | + public NameNotSpecified(DeviceId dpid) { | ||
| 62 | + super(); | ||
| 63 | + log.error("Name not specified for switch-config dpid:{}", | ||
| 64 | + dpid); | ||
| 65 | + } | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + /** | ||
| 69 | + * Exception for unspecified device type for a switch. | ||
| 70 | + */ | ||
| 71 | + public static class SwitchTypeNotSpecified extends RuntimeException { | ||
| 72 | + private static final long serialVersionUID = 2527453336226053753L; | ||
| 73 | + | ||
| 74 | + public SwitchTypeNotSpecified(DeviceId dpid) { | ||
| 75 | + super(); | ||
| 76 | + log.error("Switch type not specified for switch-config dpid:{}", | ||
| 77 | + dpid); | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + /** | ||
| 82 | + * Exception for unknown device type configured for a switch. | ||
| 83 | + */ | ||
| 84 | + public static class UnknownSwitchType extends RuntimeException { | ||
| 85 | + private static final long serialVersionUID = 7758418165512249170L; | ||
| 86 | + | ||
| 87 | + public UnknownSwitchType(String type, String name) { | ||
| 88 | + super(); | ||
| 89 | + log.error("Unknown switch type {} for switch name:{}", type, name); | ||
| 90 | + } | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + /** | ||
| 94 | + * Exception for missing required parameter configuration for a switch. | ||
| 95 | + */ | ||
| 96 | + public static class ParamsNotSpecified extends RuntimeException { | ||
| 97 | + private static final long serialVersionUID = 6247582323691265513L; | ||
| 98 | + | ||
| 99 | + public ParamsNotSpecified(String name) { | ||
| 100 | + super(); | ||
| 101 | + log.error("Params required - not specified for switch:{}", name); | ||
| 102 | + } | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + /** | ||
| 106 | + * Reserved for future use. | ||
| 107 | + */ | ||
| 108 | + public static class LinkTypeNotSpecified extends RuntimeException { | ||
| 109 | + private static final long serialVersionUID = -2089470389588542215L; | ||
| 110 | + | ||
| 111 | + public LinkTypeNotSpecified(String dpid1, String dpid2) { | ||
| 112 | + super(); | ||
| 113 | + log.error("Link type not specified for link-config between " | ||
| 114 | + + "dpid1:{} and dpid2:{}", dpid1, dpid2); | ||
| 115 | + } | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + /** | ||
| 119 | + * Reserved for future use. | ||
| 120 | + */ | ||
| 121 | + public static class LinkDpidNotSpecified extends RuntimeException { | ||
| 122 | + private static final long serialVersionUID = -5701825916378616004L; | ||
| 123 | + | ||
| 124 | + public LinkDpidNotSpecified(String dpid1, String dpid2) { | ||
| 125 | + super(); | ||
| 126 | + if (dpid1 == null) { | ||
| 127 | + log.error("nodeDpid1 not specified for link-config "); | ||
| 128 | + } | ||
| 129 | + if (dpid2 == null) { | ||
| 130 | + log.error("nodeDpid2 not specified for link-config "); | ||
| 131 | + } | ||
| 132 | + } | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + /** | ||
| 136 | + * Reserved for future use. | ||
| 137 | + */ | ||
| 138 | + public static class LinkForUnknownSwitchConfig extends RuntimeException { | ||
| 139 | + private static final long serialVersionUID = -2910458439881964094L; | ||
| 140 | + | ||
| 141 | + public LinkForUnknownSwitchConfig(String dpid) { | ||
| 142 | + super(); | ||
| 143 | + log.error("Link configuration was specified for a switch-dpid {} " | ||
| 144 | + + "that has not been configured", dpid); | ||
| 145 | + } | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + /** | ||
| 149 | + * Reserved for future use. | ||
| 150 | + */ | ||
| 151 | + public static class UnknownLinkType extends RuntimeException { | ||
| 152 | + private static final long serialVersionUID = -5505376193106542305L; | ||
| 153 | + | ||
| 154 | + public UnknownLinkType(String linktype, String dpid1, String dpid2) { | ||
| 155 | + super(); | ||
| 156 | + log.error("unknown link type {} for links between dpid1:{} " | ||
| 157 | + + "and dpid2:{}", linktype, dpid1, dpid2); | ||
| 158 | + } | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + /** | ||
| 162 | + * Exception for generic configuration errors. | ||
| 163 | + */ | ||
| 164 | + public static class ErrorConfig extends RuntimeException { | ||
| 165 | + private static final long serialVersionUID = -2827406314700193147L; | ||
| 166 | + | ||
| 167 | + public ErrorConfig(String errorMsg) { | ||
| 168 | + super(); | ||
| 169 | + log.error(errorMsg); | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + /** | ||
| 175 | + * Reserved for future use. | ||
| 176 | + */ | ||
| 177 | + public static class SwitchDpidNotConverted extends RuntimeException { | ||
| 178 | + private static final long serialVersionUID = 5640347104590170426L; | ||
| 179 | + | ||
| 180 | + public SwitchDpidNotConverted(String name) { | ||
| 181 | + super(); | ||
| 182 | + log.error("Switch dpid specified as a HexString {} does not match " | ||
| 183 | + + "with long value", name); | ||
| 184 | + } | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + /** | ||
| 188 | + * Reserved for future use. | ||
| 189 | + */ | ||
| 190 | + public static class LinkDpidNotConverted extends RuntimeException { | ||
| 191 | + private static final long serialVersionUID = 2397245646094080774L; | ||
| 192 | + | ||
| 193 | + public LinkDpidNotConverted(String dpid1, String dpid2) { | ||
| 194 | + log.error("Dpids expressed as HexStrings for links between dpid1:{} " | ||
| 195 | + + "and dpid2:{} do not match with long values", dpid1, dpid2); | ||
| 196 | + } | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | +} | ||
| 200 | + |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/NetworkConfigManager.java
0 → 100644
| 1 | +package org.onosproject.segmentrouting.config; | ||
| 2 | + | ||
| 3 | +import java.io.File; | ||
| 4 | +import java.io.IOException; | ||
| 5 | +import java.util.ArrayList; | ||
| 6 | +import java.util.HashMap; | ||
| 7 | +import java.util.HashSet; | ||
| 8 | +import java.util.List; | ||
| 9 | +import java.util.Map; | ||
| 10 | +import java.util.Set; | ||
| 11 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 12 | +import java.util.concurrent.ConcurrentMap; | ||
| 13 | + | ||
| 14 | +import org.onosproject.net.DeviceId; | ||
| 15 | +import org.onosproject.net.Link; | ||
| 16 | +import org.onosproject.segmentrouting.config.NetworkConfig.LinkConfig; | ||
| 17 | +import org.onosproject.segmentrouting.config.NetworkConfig.SwitchConfig; | ||
| 18 | +import org.slf4j.Logger; | ||
| 19 | +import org.slf4j.LoggerFactory; | ||
| 20 | + | ||
| 21 | +import com.fasterxml.jackson.core.JsonParseException; | ||
| 22 | +import com.fasterxml.jackson.databind.JsonMappingException; | ||
| 23 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * NetworkConfigManager manages all network configuration for switches, links | ||
| 27 | + * and any other state that needs to be configured for correct network | ||
| 28 | + * operation. | ||
| 29 | + * | ||
| 30 | + */ | ||
| 31 | +public class NetworkConfigManager implements NetworkConfigService { | ||
| 32 | + protected static final Logger log = LoggerFactory | ||
| 33 | + .getLogger(NetworkConfigManager.class); | ||
| 34 | + private static final String CONFIG_DIR = "../config"; | ||
| 35 | + private static final String DEFAULT_CONFIG_FILE = "segmentrouting.conf"; | ||
| 36 | + private final String configFileName = DEFAULT_CONFIG_FILE; | ||
| 37 | + /** | ||
| 38 | + * JSON Config file needs to use one of the following types for defining the | ||
| 39 | + * kind of switch or link it wishes to configure. | ||
| 40 | + */ | ||
| 41 | + public static final String SEGMENT_ROUTER = "Router_SR"; | ||
| 42 | + | ||
| 43 | + public static final String PKT_LINK = "pktLink"; | ||
| 44 | + | ||
| 45 | + NetworkConfig networkConfig; | ||
| 46 | + private ConcurrentMap<DeviceId, SwitchConfig> configuredSwitches; | ||
| 47 | + private ConcurrentMap<Link, LinkConfig> configuredLinks; | ||
| 48 | + private Map<String, DeviceId> nameToDpid; | ||
| 49 | + | ||
| 50 | + @Override | ||
| 51 | + public SwitchConfigStatus checkSwitchConfig(DeviceId dpid) { | ||
| 52 | + SwitchConfig swc = configuredSwitches.get(dpid); | ||
| 53 | + if (networkConfig.getRestrictSwitches()) { | ||
| 54 | + // default deny behavior | ||
| 55 | + if (swc == null) { | ||
| 56 | + // switch is not configured - we deny this switch | ||
| 57 | + return new SwitchConfigStatus(NetworkConfigState.DENY, null, | ||
| 58 | + "Switch not configured, in network denying switches by default."); | ||
| 59 | + } | ||
| 60 | + if (swc.isAllowed()) { | ||
| 61 | + // switch is allowed in config, return configured attributes | ||
| 62 | + return new SwitchConfigStatus(NetworkConfigState.ACCEPT_ADD, swc); | ||
| 63 | + } else { | ||
| 64 | + // switch has been configured off (administratively down) | ||
| 65 | + return new SwitchConfigStatus(NetworkConfigState.DENY, null, | ||
| 66 | + "Switch configured down (allowed=false)."); | ||
| 67 | + } | ||
| 68 | + } else { | ||
| 69 | + // default allow behavior | ||
| 70 | + if (swc == null) { | ||
| 71 | + // no config to add | ||
| 72 | + return new SwitchConfigStatus(NetworkConfigState.ACCEPT, null); | ||
| 73 | + } | ||
| 74 | + if (swc.isAllowed()) { | ||
| 75 | + // switch is allowed in config, return configured attributes | ||
| 76 | + return new SwitchConfigStatus(NetworkConfigState.ACCEPT_ADD, swc); | ||
| 77 | + } else { | ||
| 78 | + // switch has been configured off (administratively down) | ||
| 79 | + return new SwitchConfigStatus(NetworkConfigState.DENY, null, | ||
| 80 | + "Switch configured down (allowed=false)."); | ||
| 81 | + } | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + @Override | ||
| 87 | + public LinkConfigStatus checkLinkConfig(Link linkTuple) { | ||
| 88 | + LinkConfig lkc = getConfiguredLink(linkTuple); | ||
| 89 | + // links are always disallowed if any one of the nodes that make up the | ||
| 90 | + // link are disallowed | ||
| 91 | + DeviceId linkNode1 = linkTuple.src().deviceId(); | ||
| 92 | + SwitchConfigStatus scs1 = checkSwitchConfig(linkNode1); | ||
| 93 | + if (scs1.getConfigState() == NetworkConfigState.DENY) { | ||
| 94 | + return new LinkConfigStatus(NetworkConfigState.DENY, null, | ||
| 95 | + "Link-node: " + linkNode1 + " denied by config: " + scs1.getMsg()); | ||
| 96 | + } | ||
| 97 | + DeviceId linkNode2 = linkTuple.dst().deviceId(); | ||
| 98 | + SwitchConfigStatus scs2 = checkSwitchConfig(linkNode2); | ||
| 99 | + if (scs2.getConfigState() == NetworkConfigState.DENY) { | ||
| 100 | + return new LinkConfigStatus(NetworkConfigState.DENY, null, | ||
| 101 | + "Link-node: " + linkNode2 + " denied by config: " + scs2.getMsg()); | ||
| 102 | + } | ||
| 103 | + if (networkConfig.getRestrictLinks()) { | ||
| 104 | + // default deny behavior | ||
| 105 | + if (lkc == null) { | ||
| 106 | + // link is not configured - we deny this link | ||
| 107 | + return new LinkConfigStatus(NetworkConfigState.DENY, null, | ||
| 108 | + "Link not configured, in network denying links by default."); | ||
| 109 | + } | ||
| 110 | + if (lkc.isAllowed()) { | ||
| 111 | + // link is allowed in config, return configured attributes | ||
| 112 | + return new LinkConfigStatus(NetworkConfigState.ACCEPT_ADD, lkc); | ||
| 113 | + } else { | ||
| 114 | + // link has been configured off (administratively down) | ||
| 115 | + return new LinkConfigStatus(NetworkConfigState.DENY, null, | ||
| 116 | + "Link configured down (allowed=false)."); | ||
| 117 | + } | ||
| 118 | + } else { | ||
| 119 | + // default allow behavior | ||
| 120 | + if (lkc == null) { | ||
| 121 | + // no config to add | ||
| 122 | + return new LinkConfigStatus(NetworkConfigState.ACCEPT, null); | ||
| 123 | + } | ||
| 124 | + if (lkc.isAllowed()) { | ||
| 125 | + // link is allowed in config, return configured attributes | ||
| 126 | + return new LinkConfigStatus(NetworkConfigState.ACCEPT_ADD, lkc); | ||
| 127 | + } else { | ||
| 128 | + // link has been configured off (administratively down) | ||
| 129 | + return new LinkConfigStatus(NetworkConfigState.DENY, null, | ||
| 130 | + "Link configured down (allowed=false)."); | ||
| 131 | + } | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + @Override | ||
| 137 | + public List<SwitchConfig> getConfiguredAllowedSwitches() { | ||
| 138 | + List<SwitchConfig> allowed = new ArrayList<SwitchConfig>(); | ||
| 139 | + for (SwitchConfig swc : configuredSwitches.values()) { | ||
| 140 | + if (swc.isAllowed()) { | ||
| 141 | + allowed.add(swc); | ||
| 142 | + } | ||
| 143 | + } | ||
| 144 | + return allowed; | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + @Override | ||
| 148 | + public List<LinkConfig> getConfiguredAllowedLinks() { | ||
| 149 | + List<LinkConfig> allowed = new ArrayList<LinkConfig>(); | ||
| 150 | + for (LinkConfig lkc : configuredLinks.values()) { | ||
| 151 | + if (lkc.isAllowed()) { | ||
| 152 | + allowed.add(lkc); | ||
| 153 | + } | ||
| 154 | + } | ||
| 155 | + return allowed; | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + @Override | ||
| 159 | + public DeviceId getDpidForName(String name) { | ||
| 160 | + if (nameToDpid.get(name) != null) { | ||
| 161 | + return nameToDpid.get(name); | ||
| 162 | + } | ||
| 163 | + return null; | ||
| 164 | + } | ||
| 165 | + | ||
| 166 | + // ************** | ||
| 167 | + // Private methods | ||
| 168 | + // ************** | ||
| 169 | + | ||
| 170 | + private void loadNetworkConfig() { | ||
| 171 | + File configFile = new File(CONFIG_DIR, configFileName); | ||
| 172 | + ObjectMapper mapper = new ObjectMapper(); | ||
| 173 | + networkConfig = new NetworkConfig(); | ||
| 174 | + | ||
| 175 | + try { | ||
| 176 | + networkConfig = mapper.readValue(configFile, | ||
| 177 | + NetworkConfig.class); | ||
| 178 | + } catch (JsonParseException e) { | ||
| 179 | + String err = String.format("JsonParseException while loading network " | ||
| 180 | + + "config from file: %s: %s", configFileName, | ||
| 181 | + e.getMessage()); | ||
| 182 | + throw new NetworkConfigException.ErrorConfig(err); | ||
| 183 | + } catch (JsonMappingException e) { | ||
| 184 | + String err = String.format( | ||
| 185 | + "JsonMappingException while loading network config " | ||
| 186 | + + "from file: %s: %s", | ||
| 187 | + configFileName, | ||
| 188 | + e.getMessage()); | ||
| 189 | + throw new NetworkConfigException.ErrorConfig(err); | ||
| 190 | + } catch (IOException e) { | ||
| 191 | + String err = String.format("IOException while loading network config " | ||
| 192 | + + "from file: %s %s", configFileName, e.getMessage()); | ||
| 193 | + throw new NetworkConfigException.ErrorConfig(err); | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + log.info("Network config specifies: {} switches and {} links", | ||
| 197 | + (networkConfig.getRestrictSwitches()) | ||
| 198 | + ? networkConfig.getSwitchConfig().size() : "default allow", | ||
| 199 | + (networkConfig.getRestrictLinks()) | ||
| 200 | + ? networkConfig.getLinkConfig().size() : "default allow"); | ||
| 201 | + } | ||
| 202 | + | ||
| 203 | + private void parseNetworkConfig() { | ||
| 204 | + List<SwitchConfig> swConfList = networkConfig.getSwitchConfig(); | ||
| 205 | + List<LinkConfig> lkConfList = networkConfig.getLinkConfig(); | ||
| 206 | + validateSwitchConfig(swConfList); | ||
| 207 | + createTypeSpecificSwitchConfig(swConfList); | ||
| 208 | + validateLinkConfig(lkConfList); | ||
| 209 | + createTypeSpecificLinkConfig(lkConfList); | ||
| 210 | + // TODO validate reachability matrix 'names' for configured dpids | ||
| 211 | + } | ||
| 212 | + | ||
| 213 | + private void createTypeSpecificSwitchConfig(List<SwitchConfig> swConfList) { | ||
| 214 | + for (SwitchConfig swc : swConfList) { | ||
| 215 | + nameToDpid.put(swc.getName(), swc.getDpid()); | ||
| 216 | + String swtype = swc.getType(); | ||
| 217 | + switch (swtype) { | ||
| 218 | + case SEGMENT_ROUTER: | ||
| 219 | + SwitchConfig sr = new SegmentRouterConfig(swc); | ||
| 220 | + configuredSwitches.put(sr.getDpid(), sr); | ||
| 221 | + break; | ||
| 222 | + default: | ||
| 223 | + throw new NetworkConfigException.UnknownSwitchType(swtype, | ||
| 224 | + swc.getName()); | ||
| 225 | + } | ||
| 226 | + } | ||
| 227 | + } | ||
| 228 | + | ||
| 229 | + private void createTypeSpecificLinkConfig(List<LinkConfig> lkConfList) { | ||
| 230 | + for (LinkConfig lkc : lkConfList) { | ||
| 231 | + String lktype = lkc.getType(); | ||
| 232 | + switch (lktype) { | ||
| 233 | + case PKT_LINK: | ||
| 234 | + PktLinkConfig pk = new PktLinkConfig(lkc); | ||
| 235 | + for (Link lt : pk.getLinkTupleList()) { | ||
| 236 | + configuredLinks.put(lt, pk); | ||
| 237 | + } | ||
| 238 | + break; | ||
| 239 | + default: | ||
| 240 | + throw new NetworkConfigException.UnknownLinkType(lktype, | ||
| 241 | + lkc.getNodeDpid1(), lkc.getNodeDpid2()); | ||
| 242 | + } | ||
| 243 | + } | ||
| 244 | + } | ||
| 245 | + | ||
| 246 | + private void validateSwitchConfig(List<SwitchConfig> swConfList) { | ||
| 247 | + Set<DeviceId> swDpids = new HashSet<DeviceId>(); | ||
| 248 | + Set<String> swNames = new HashSet<String>(); | ||
| 249 | + for (SwitchConfig swc : swConfList) { | ||
| 250 | + if (swc.getNodeDpid() == null || swc.getDpid() == null) { | ||
| 251 | + throw new NetworkConfigException.DpidNotSpecified(swc.getName()); | ||
| 252 | + } | ||
| 253 | + // ensure both String and DeviceId values of dpid are set | ||
| 254 | + if (!swc.getDpid().equals(DeviceId.deviceId(swc.getNodeDpid()))) { | ||
| 255 | + throw new NetworkConfigException.SwitchDpidNotConverted( | ||
| 256 | + swc.getName()); | ||
| 257 | + } | ||
| 258 | + if (swc.getName() == null) { | ||
| 259 | + throw new NetworkConfigException.NameNotSpecified(swc.getDpid()); | ||
| 260 | + } | ||
| 261 | + if (swc.getType() == null) { | ||
| 262 | + throw new NetworkConfigException.SwitchTypeNotSpecified( | ||
| 263 | + swc.getDpid()); | ||
| 264 | + } | ||
| 265 | + if (!swDpids.add(swc.getDpid())) { | ||
| 266 | + throw new NetworkConfigException.DuplicateDpid(swc.getDpid()); | ||
| 267 | + } | ||
| 268 | + if (!swNames.add(swc.getName())) { | ||
| 269 | + throw new NetworkConfigException.DuplicateName(swc.getName()); | ||
| 270 | + } | ||
| 271 | + // TODO Add more validations | ||
| 272 | + } | ||
| 273 | + } | ||
| 274 | + | ||
| 275 | + private void validateLinkConfig(List<LinkConfig> lkConfList) { | ||
| 276 | + for (LinkConfig lkc : lkConfList) { | ||
| 277 | + if (lkc.getNodeDpid1() == null || lkc.getNodeDpid2() == null) { | ||
| 278 | + throw new NetworkConfigException.LinkDpidNotSpecified( | ||
| 279 | + lkc.getNodeDpid1(), lkc.getNodeDpid2()); | ||
| 280 | + } | ||
| 281 | + // ensure both String and Long values are set | ||
| 282 | + if (!lkc.getDpid1().equals(DeviceId.deviceId(lkc.getNodeDpid1())) || | ||
| 283 | + !lkc.getDpid2().equals(DeviceId.deviceId(lkc.getNodeDpid2()))) { | ||
| 284 | + throw new NetworkConfigException.LinkDpidNotConverted( | ||
| 285 | + lkc.getNodeDpid1(), lkc.getNodeDpid2()); | ||
| 286 | + } | ||
| 287 | + if (lkc.getType() == null) { | ||
| 288 | + throw new NetworkConfigException.LinkTypeNotSpecified( | ||
| 289 | + lkc.getNodeDpid1(), lkc.getNodeDpid2()); | ||
| 290 | + } | ||
| 291 | + if (configuredSwitches.get(lkc.getDpid1()) == null) { | ||
| 292 | + throw new NetworkConfigException.LinkForUnknownSwitchConfig( | ||
| 293 | + lkc.getNodeDpid1()); | ||
| 294 | + } | ||
| 295 | + if (configuredSwitches.get(lkc.getDpid2()) == null) { | ||
| 296 | + throw new NetworkConfigException.LinkForUnknownSwitchConfig( | ||
| 297 | + lkc.getNodeDpid2()); | ||
| 298 | + } | ||
| 299 | + // TODO add more validations | ||
| 300 | + } | ||
| 301 | + | ||
| 302 | + } | ||
| 303 | + | ||
| 304 | + private LinkConfig getConfiguredLink(Link linkTuple) { | ||
| 305 | + LinkConfig lkc = null; | ||
| 306 | + // first try the unidirectional link with the ports assigned | ||
| 307 | + lkc = configuredLinks.get(linkTuple); | ||
| 308 | + return lkc; | ||
| 309 | + } | ||
| 310 | + | ||
| 311 | + | ||
| 312 | + /** | ||
| 313 | + * Initializes the network configuration manager module by | ||
| 314 | + * loading and parsing the network configuration file. | ||
| 315 | + */ | ||
| 316 | + public void init() { | ||
| 317 | + loadNetworkConfig(); | ||
| 318 | + configuredSwitches = new ConcurrentHashMap<DeviceId, SwitchConfig>(); | ||
| 319 | + configuredLinks = new ConcurrentHashMap<Link, LinkConfig>(); | ||
| 320 | + nameToDpid = new HashMap<String, DeviceId>(); | ||
| 321 | + parseNetworkConfig(); | ||
| 322 | + } | ||
| 323 | +} |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/NetworkConfigService.java
0 → 100644
| 1 | +package org.onosproject.segmentrouting.config; | ||
| 2 | + | ||
| 3 | +import java.util.List; | ||
| 4 | + | ||
| 5 | +import org.onosproject.net.DeviceId; | ||
| 6 | +import org.onosproject.net.Link; | ||
| 7 | +import org.onosproject.segmentrouting.config.NetworkConfig.LinkConfig; | ||
| 8 | +import org.onosproject.segmentrouting.config.NetworkConfig.SwitchConfig; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * Exposes methods to retrieve network configuration. | ||
| 12 | + * | ||
| 13 | + * TODO: currently only startup-configuration is exposed and such configuration | ||
| 14 | + * cannot be changed at runtime. Need to add runtime support for changes to | ||
| 15 | + * configuration (via REST/CLI) in future releases. | ||
| 16 | + * | ||
| 17 | + * TODO: return immutable objects or defensive copies of network config so that | ||
| 18 | + * users of this API do not inadvertently or maliciously change network config. | ||
| 19 | + */ | ||
| 20 | +public interface NetworkConfigService { | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * Suggests the action to be taken by the caller given the configuration | ||
| 24 | + * associated with the queried network-object (eg. switch, link etc.). | ||
| 25 | + */ | ||
| 26 | + public enum NetworkConfigState { | ||
| 27 | + /** | ||
| 28 | + * Associated network object has been configured to not be allowed in | ||
| 29 | + * the network. | ||
| 30 | + */ | ||
| 31 | + DENY, | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * Associated network object has been configured to be allowed in the | ||
| 35 | + * network. | ||
| 36 | + */ | ||
| 37 | + ACCEPT, | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * Associated network object has been configured to be allowed in the | ||
| 41 | + * network. In addition, there are configured parameters that should be | ||
| 42 | + * added to the object. | ||
| 43 | + */ | ||
| 44 | + ACCEPT_ADD, | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + /** | ||
| 48 | + * Returns the configuration outcome (accept, deny etc.), and any configured | ||
| 49 | + * parameters to the caller, in response to a query for the configuration | ||
| 50 | + * associated with a switch. | ||
| 51 | + */ | ||
| 52 | + public class SwitchConfigStatus { | ||
| 53 | + private NetworkConfigState configState; | ||
| 54 | + private SwitchConfig switchConfig; | ||
| 55 | + private String msg; | ||
| 56 | + | ||
| 57 | + SwitchConfigStatus(NetworkConfigState configState, | ||
| 58 | + SwitchConfig switchConfig, String msg) { | ||
| 59 | + this.configState = configState; | ||
| 60 | + this.switchConfig = switchConfig; | ||
| 61 | + this.msg = msg; | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + SwitchConfigStatus(NetworkConfigState configState, | ||
| 65 | + SwitchConfig switchConfig) { | ||
| 66 | + this.configState = configState; | ||
| 67 | + this.switchConfig = switchConfig; | ||
| 68 | + this.msg = ""; | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * Returns the configuration state for the switch. | ||
| 73 | + * | ||
| 74 | + * @return non-null NetworkConfigState | ||
| 75 | + */ | ||
| 76 | + public NetworkConfigState getConfigState() { | ||
| 77 | + return configState; | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + /** | ||
| 81 | + * Returns the switch configuration, which may be null if no | ||
| 82 | + * configuration exists, or if the configuration state disallows the | ||
| 83 | + * switch. | ||
| 84 | + * | ||
| 85 | + * @return SwitchConfig, the switch configuration, or null | ||
| 86 | + */ | ||
| 87 | + public SwitchConfig getSwitchConfig() { | ||
| 88 | + return switchConfig; | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + /** | ||
| 92 | + * User readable string typically used to specify the reason why a | ||
| 93 | + * switch is being disallowed. | ||
| 94 | + * | ||
| 95 | + * @return A non-null but possibly empty String | ||
| 96 | + */ | ||
| 97 | + public String getMsg() { | ||
| 98 | + return msg; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + /** | ||
| 104 | + * Reserved for future use. | ||
| 105 | + * | ||
| 106 | + * Returns the configuration outcome (accept, deny etc.), and any configured | ||
| 107 | + * parameters to the caller, in response to a query for the configuration | ||
| 108 | + * associated with a link. | ||
| 109 | + */ | ||
| 110 | + public class LinkConfigStatus { | ||
| 111 | + private NetworkConfigState configState; | ||
| 112 | + private LinkConfig linkConfig; | ||
| 113 | + private String msg; | ||
| 114 | + | ||
| 115 | + LinkConfigStatus(NetworkConfigState configState, | ||
| 116 | + LinkConfig linkConfig, String msg) { | ||
| 117 | + this.configState = configState; | ||
| 118 | + this.linkConfig = linkConfig; | ||
| 119 | + this.msg = msg; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + LinkConfigStatus(NetworkConfigState configState, | ||
| 123 | + LinkConfig linkConfig) { | ||
| 124 | + this.configState = configState; | ||
| 125 | + this.linkConfig = linkConfig; | ||
| 126 | + this.msg = ""; | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + /** | ||
| 130 | + * Returns the configuration state for the link. | ||
| 131 | + * | ||
| 132 | + * @return non-null NetworkConfigState | ||
| 133 | + */ | ||
| 134 | + public NetworkConfigState getConfigState() { | ||
| 135 | + return configState; | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + /** | ||
| 139 | + * Returns the link configuration, which may be null if no configuration | ||
| 140 | + * exists, or if the configuration state disallows the link. | ||
| 141 | + * | ||
| 142 | + * @return SwitchConfig, the switch configuration, or null | ||
| 143 | + */ | ||
| 144 | + public LinkConfig getLinkConfig() { | ||
| 145 | + return linkConfig; | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + /** | ||
| 149 | + * User readable string typically used to specify the reason why a link | ||
| 150 | + * is being disallowed. | ||
| 151 | + * | ||
| 152 | + * @return msg A non-null but possibly empty String | ||
| 153 | + */ | ||
| 154 | + public String getMsg() { | ||
| 155 | + return msg; | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + /** | ||
| 161 | + * Checks the switch configuration (if any) associated with the 'dpid'. | ||
| 162 | + * Determines if the switch should be allowed or denied according to | ||
| 163 | + * configuration rules. | ||
| 164 | + * | ||
| 165 | + * The method always returns a non-null SwitchConfigStatus. The enclosed | ||
| 166 | + * ConfigState contains the result of the check. The enclosed SwitchConfig | ||
| 167 | + * may or may not be null, depending on the outcome of the check. | ||
| 168 | + * | ||
| 169 | + * @param dpid device id of the switch to be queried | ||
| 170 | + * @return SwitchConfigStatus with outcome of check and associated config. | ||
| 171 | + */ | ||
| 172 | + public SwitchConfigStatus checkSwitchConfig(DeviceId dpid); | ||
| 173 | + | ||
| 174 | + /** | ||
| 175 | + * Reserved for future use. | ||
| 176 | + * | ||
| 177 | + * Checks the link configuration (if any) associated with the 'link'. | ||
| 178 | + * Determines if the link should be allowed or denied according to | ||
| 179 | + * configuration rules. Note that the 'link' is a unidirectional link which | ||
| 180 | + * checked against configuration that is typically defined for a | ||
| 181 | + * bidirectional link. The caller may make a second call if it wishes to | ||
| 182 | + * check the 'reverse' direction. | ||
| 183 | + * | ||
| 184 | + * Also note that the configuration may not specify ports for a given | ||
| 185 | + * bidirectional link. In such cases, the configuration applies to all links | ||
| 186 | + * between the two switches. This method will check the given 'link' against | ||
| 187 | + * such configuration. | ||
| 188 | + | ||
| 189 | + * The method always returns a non-null LinkConfigStatus. The enclosed | ||
| 190 | + * ConfigState contains the result of the check. The enclosed LinkConfig may | ||
| 191 | + * or may not be null, depending on the outcome of the check. | ||
| 192 | + * | ||
| 193 | + * @param linkTuple unidirectional link to be queried | ||
| 194 | + * @return LinkConfigStatus with outcome of check and associated config. | ||
| 195 | + */ | ||
| 196 | + public LinkConfigStatus checkLinkConfig(Link linkTuple); | ||
| 197 | + | ||
| 198 | + /** | ||
| 199 | + * Retrieves a list of switches that have been configured, and have been | ||
| 200 | + * determined to be 'allowed' in the network, according to configuration | ||
| 201 | + * rules. | ||
| 202 | + * | ||
| 203 | + * Note that it is possible that there are other switches that are allowed | ||
| 204 | + * in the network that have NOT been configured. Such switches will not be a | ||
| 205 | + * part of the returned list. | ||
| 206 | + * | ||
| 207 | + * Also note that it is possible that some switches will not be discovered | ||
| 208 | + * and the only way the controller can know about these switches is via | ||
| 209 | + * configuration. Such switches will be included in this list. It is up to | ||
| 210 | + * the caller to determine which SwitchConfig applies to non-discovered | ||
| 211 | + * switches. | ||
| 212 | + * | ||
| 213 | + * @return a non-null List of SwitchConfig which may be empty | ||
| 214 | + */ | ||
| 215 | + public List<SwitchConfig> getConfiguredAllowedSwitches(); | ||
| 216 | + | ||
| 217 | + /** | ||
| 218 | + * Reserved for future use. | ||
| 219 | + * | ||
| 220 | + * Retrieves a list of links that have been configured, and have been | ||
| 221 | + * determined to be 'allowed' in the network, according to configuration | ||
| 222 | + * rules. | ||
| 223 | + * | ||
| 224 | + * Note that it is possible that there are other links that are allowed in | ||
| 225 | + * the network that have NOT been configured. Such links will not be a part | ||
| 226 | + * of the returned list. | ||
| 227 | + * | ||
| 228 | + * Also note that it is possible that some links will not be discovered and | ||
| 229 | + * the only way the controller can know about these links is via | ||
| 230 | + * configuration. Such links will be included in this list. It is up to the | ||
| 231 | + * caller to determine which LinkConfig applies to non-discovered links. | ||
| 232 | + * | ||
| 233 | + * In addition, note that the LinkConfig applies to the configured | ||
| 234 | + * bi-directional link, which may or may not have declared ports. The | ||
| 235 | + * associated unidirectional LinkTuple can be retrieved from the | ||
| 236 | + * getLinkTupleList() method in the LinkConfig object. | ||
| 237 | + * | ||
| 238 | + * @return a non-null List of LinkConfig which may be empty | ||
| 239 | + */ | ||
| 240 | + public List<LinkConfig> getConfiguredAllowedLinks(); | ||
| 241 | + | ||
| 242 | + /** | ||
| 243 | + * Retrieves the Dpid associated with a 'name' for a configured switch | ||
| 244 | + * object. This method does not check of the switches are 'allowed' by | ||
| 245 | + * config. | ||
| 246 | + * | ||
| 247 | + * @param name device name | ||
| 248 | + * @return the Dpid corresponding to a given 'name', or null if no | ||
| 249 | + * configured switch was found for the given 'name'. | ||
| 250 | + */ | ||
| 251 | + public DeviceId getDpidForName(String name); | ||
| 252 | + | ||
| 253 | +} |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/PktLinkConfig.java
0 → 100644
| 1 | +package org.onosproject.segmentrouting.config; | ||
| 2 | + | ||
| 3 | +import java.util.List; | ||
| 4 | +import java.util.Map.Entry; | ||
| 5 | +import java.util.Set; | ||
| 6 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 7 | + | ||
| 8 | +import org.onosproject.net.Link; | ||
| 9 | +import org.onosproject.segmentrouting.config.NetworkConfig.LinkConfig; | ||
| 10 | +import org.slf4j.Logger; | ||
| 11 | +import org.slf4j.LoggerFactory; | ||
| 12 | + | ||
| 13 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * Reserved for future use. | ||
| 17 | + * Configuration for a link between two packet-switches. | ||
| 18 | + */ | ||
| 19 | +public class PktLinkConfig extends LinkConfig { | ||
| 20 | + protected static final Logger log = LoggerFactory | ||
| 21 | + .getLogger(PktLinkConfig.class); | ||
| 22 | + private int port1; | ||
| 23 | + private int port2; | ||
| 24 | + private String nodeName1; | ||
| 25 | + private String nodeName2; | ||
| 26 | + private List<Link> linkTupleList; | ||
| 27 | + | ||
| 28 | + public PktLinkConfig(LinkConfig lkc) { | ||
| 29 | + nodeDpid1 = lkc.getNodeDpid1(); | ||
| 30 | + nodeDpid2 = lkc.getNodeDpid2(); | ||
| 31 | + dpid1 = lkc.getDpid1(); | ||
| 32 | + dpid2 = lkc.getDpid2(); | ||
| 33 | + type = lkc.getType(); | ||
| 34 | + allowed = lkc.isAllowed(); | ||
| 35 | + params = lkc.getParams(); | ||
| 36 | + publishAttributes = new ConcurrentHashMap<String, String>(); | ||
| 37 | + parseParams(); | ||
| 38 | + validateParams(); | ||
| 39 | + setPublishAttributes(); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + // ******************** | ||
| 43 | + // Packet Link Configuration | ||
| 44 | + // ******************** | ||
| 45 | + | ||
| 46 | + public int getPort1() { | ||
| 47 | + return port1; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + public void setPort1(int port1) { | ||
| 51 | + this.port1 = port1; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + public int getPort2() { | ||
| 55 | + return port2; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + public void setPort2(int port2) { | ||
| 59 | + this.port2 = port2; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + public String getNodeName1() { | ||
| 63 | + return nodeName1; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + public void setNodeName1(String nodeName1) { | ||
| 67 | + this.nodeName1 = nodeName1; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + public String getNodeName2() { | ||
| 71 | + return nodeName2; | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + public void setNodeName2(String nodeName2) { | ||
| 75 | + this.nodeName2 = nodeName2; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + /** | ||
| 79 | + * Returns the two unidirectional links corresponding to the packet-link | ||
| 80 | + * configuration. It is possible that the ports in the LinkTuple have | ||
| 81 | + * portnumber '0', implying that the configuration applies to all links | ||
| 82 | + * between the two switches. | ||
| 83 | + * | ||
| 84 | + * @return a list of LinkTuple with exactly 2 unidirectional links | ||
| 85 | + */ | ||
| 86 | + public List<Link> getLinkTupleList() { | ||
| 87 | + return linkTupleList; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + private void setPublishAttributes() { | ||
| 91 | + | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + private void parseParams() { | ||
| 95 | + if (params == null) { | ||
| 96 | + throw new PktLinkParamsNotSpecified(nodeDpid1, nodeDpid2); | ||
| 97 | + } | ||
| 98 | + Set<Entry<String, JsonNode>> m = params.entrySet(); | ||
| 99 | + for (Entry<String, JsonNode> e : m) { | ||
| 100 | + String key = e.getKey(); | ||
| 101 | + JsonNode j = e.getValue(); | ||
| 102 | + if (key.equals("nodeName1")) { | ||
| 103 | + setNodeName1(j.asText()); | ||
| 104 | + } else if (key.equals("nodeName2")) { | ||
| 105 | + setNodeName2(j.asText()); | ||
| 106 | + } else if (key.equals("port1")) { | ||
| 107 | + setPort1(j.asInt()); | ||
| 108 | + } else if (key.equals("port2")) { | ||
| 109 | + setPort2(j.asInt()); | ||
| 110 | + } else { | ||
| 111 | + throw new UnknownPktLinkConfig(key, nodeDpid1, nodeDpid2); | ||
| 112 | + } | ||
| 113 | + } | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + private void validateParams() { | ||
| 117 | + // TODO - wrong-names, duplicate links, | ||
| 118 | + // duplicate use of port, is switch-allowed for which link is allowed? | ||
| 119 | + // valid port numbers | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + public static class PktLinkParamsNotSpecified extends RuntimeException { | ||
| 123 | + private static final long serialVersionUID = 6247582323691265513L; | ||
| 124 | + | ||
| 125 | + public PktLinkParamsNotSpecified(String dpidA, String dpidB) { | ||
| 126 | + super(); | ||
| 127 | + log.error("Params required for packet link - not specified " | ||
| 128 | + + "for link between switch1:{} and switch2:{}", | ||
| 129 | + dpidA, dpidB); | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + public static class UnknownPktLinkConfig extends RuntimeException { | ||
| 134 | + private static final long serialVersionUID = -5750132094884129179L; | ||
| 135 | + | ||
| 136 | + public UnknownPktLinkConfig(String key, String dpidA, String dpidB) { | ||
| 137 | + super(); | ||
| 138 | + log.error("Unknown packet-link config {} for link between" | ||
| 139 | + + " dpid1: {} and dpid2: {}", key, | ||
| 140 | + dpidA, dpidB); | ||
| 141 | + } | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | +} |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/SegmentRouterConfig.java
0 → 100644
| 1 | +package org.onosproject.segmentrouting.config; | ||
| 2 | + | ||
| 3 | +import java.io.IOException; | ||
| 4 | +import java.util.ArrayList; | ||
| 5 | +import java.util.Iterator; | ||
| 6 | +import java.util.List; | ||
| 7 | +import java.util.Map.Entry; | ||
| 8 | +import java.util.Set; | ||
| 9 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 10 | + | ||
| 11 | +import org.onosproject.net.DeviceId; | ||
| 12 | +import org.onosproject.segmentrouting.config.NetworkConfig.SwitchConfig; | ||
| 13 | +import org.slf4j.Logger; | ||
| 14 | +import org.slf4j.LoggerFactory; | ||
| 15 | + | ||
| 16 | +import com.fasterxml.jackson.core.JsonProcessingException; | ||
| 17 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 18 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 19 | + | ||
| 20 | +/** | ||
| 21 | + * Manages additional configuration for switches configured as Segment Routers. | ||
| 22 | + */ | ||
| 23 | +public class SegmentRouterConfig extends SwitchConfig { | ||
| 24 | + protected static final Logger log = LoggerFactory | ||
| 25 | + .getLogger(SegmentRouterConfig.class); | ||
| 26 | + private String routerIp; | ||
| 27 | + private String routerMac; | ||
| 28 | + private int nodeSid; | ||
| 29 | + private boolean isEdgeRouter; | ||
| 30 | + private List<AdjacencySid> adjacencySids; | ||
| 31 | + private List<Subnet> subnets; | ||
| 32 | + | ||
| 33 | + public static final String ROUTER_IP = "routerIp"; | ||
| 34 | + public static final String ROUTER_MAC = "routerMac"; | ||
| 35 | + public static final String NODE_SID = "nodeSid"; | ||
| 36 | + public static final String ADJACENCY_SIDS = "adjacencySids"; | ||
| 37 | + public static final String SUBNETS = "subnets"; | ||
| 38 | + public static final String ISEDGE = "isEdgeRouter"; | ||
| 39 | + private static final int SRGB_MAX = 1000; | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * Parses and validates the additional configuration parameters applicable | ||
| 43 | + * to segment routers. | ||
| 44 | + * | ||
| 45 | + * @param swc switch configuration | ||
| 46 | + */ | ||
| 47 | + public SegmentRouterConfig(SwitchConfig swc) { | ||
| 48 | + this.setName(swc.getName()); | ||
| 49 | + this.setDpid(swc.getDpid()); | ||
| 50 | + this.setType(swc.getType()); | ||
| 51 | + this.setLatitude(swc.getLatitude()); | ||
| 52 | + this.setLongitude(swc.getLongitude()); | ||
| 53 | + this.setParams(swc.getParams()); | ||
| 54 | + this.setAllowed(swc.isAllowed()); | ||
| 55 | + publishAttributes = new ConcurrentHashMap<String, String>(); | ||
| 56 | + adjacencySids = new ArrayList<AdjacencySid>(); | ||
| 57 | + subnets = new ArrayList<Subnet>(); | ||
| 58 | + parseParams(); | ||
| 59 | + validateParams(); | ||
| 60 | + setPublishAttributes(); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * Returns the configured segment router IP address. | ||
| 65 | + * | ||
| 66 | + * @return ip address in string format | ||
| 67 | + */ | ||
| 68 | + public String getRouterIp() { | ||
| 69 | + return routerIp; | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + public void setRouterIp(String routerIp) { | ||
| 73 | + this.routerIp = routerIp; | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * Returns the configured segment router mac address. | ||
| 78 | + * | ||
| 79 | + * @return mac address in string format | ||
| 80 | + */ | ||
| 81 | + public String getRouterMac() { | ||
| 82 | + return routerMac; | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + public void setRouterMac(String routerMac) { | ||
| 86 | + this.routerMac = routerMac; | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + /** | ||
| 90 | + * Returns the configured sID for a segment router. | ||
| 91 | + * | ||
| 92 | + * @return segment identifier | ||
| 93 | + */ | ||
| 94 | + public int getNodeSid() { | ||
| 95 | + return nodeSid; | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + public void setNodeSid(int nodeSid) { | ||
| 99 | + this.nodeSid = nodeSid; | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + /** | ||
| 103 | + * Returns the flag that indicates the configured segment router | ||
| 104 | + * is edge or backbone router. | ||
| 105 | + * | ||
| 106 | + * @return boolean | ||
| 107 | + */ | ||
| 108 | + public boolean isEdgeRouter() { | ||
| 109 | + return isEdgeRouter; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + public void setIsEdgeRouter(boolean isEdge) { | ||
| 113 | + this.isEdgeRouter = isEdge; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + /** | ||
| 117 | + * Class representing segment router adjacency identifier. | ||
| 118 | + */ | ||
| 119 | + public static class AdjacencySid { | ||
| 120 | + private int adjSid; | ||
| 121 | + private List<Integer> ports; | ||
| 122 | + | ||
| 123 | + public AdjacencySid(int adjSid, List<Integer> ports) { | ||
| 124 | + this.ports = ports; | ||
| 125 | + this.adjSid = adjSid; | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + /** | ||
| 129 | + * Returns the list of ports part of a segment | ||
| 130 | + * router adjacency identifier. | ||
| 131 | + * | ||
| 132 | + * @return list of integers | ||
| 133 | + */ | ||
| 134 | + public List<Integer> getPorts() { | ||
| 135 | + return ports; | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + public void setPorts(List<Integer> ports) { | ||
| 139 | + this.ports = ports; | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + /** | ||
| 143 | + * Returns the configured adjacency id of a segment router. | ||
| 144 | + * | ||
| 145 | + * @return integer | ||
| 146 | + */ | ||
| 147 | + public int getAdjSid() { | ||
| 148 | + return adjSid; | ||
| 149 | + } | ||
| 150 | + | ||
| 151 | + public void setAdjSid(int adjSid) { | ||
| 152 | + this.adjSid = adjSid; | ||
| 153 | + } | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + /** | ||
| 157 | + * Returns the configured adjacent segment IDs for a segment router. | ||
| 158 | + * | ||
| 159 | + * @return list of adjacency identifier | ||
| 160 | + */ | ||
| 161 | + public List<AdjacencySid> getAdjacencySids() { | ||
| 162 | + return adjacencySids; | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + public void setAdjacencySids(List<AdjacencySid> adjacencySids) { | ||
| 166 | + this.adjacencySids = adjacencySids; | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + /** | ||
| 170 | + * Class representing a subnet attached to a segment router. | ||
| 171 | + */ | ||
| 172 | + public static class Subnet { | ||
| 173 | + private int portNo; | ||
| 174 | + private String subnetIp; | ||
| 175 | + | ||
| 176 | + public Subnet(int portNo, String subnetIp) { | ||
| 177 | + this.portNo = portNo; | ||
| 178 | + this.subnetIp = subnetIp; | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + /** | ||
| 182 | + * Returns the port number of segment router on | ||
| 183 | + * which subnet is attached. | ||
| 184 | + * | ||
| 185 | + * @return integer | ||
| 186 | + */ | ||
| 187 | + public int getPortNo() { | ||
| 188 | + return portNo; | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + public void setPortNo(int portNo) { | ||
| 192 | + this.portNo = portNo; | ||
| 193 | + } | ||
| 194 | + | ||
| 195 | + /** | ||
| 196 | + * Returns the configured subnet address. | ||
| 197 | + * | ||
| 198 | + * @return subnet ip address in string format | ||
| 199 | + */ | ||
| 200 | + public String getSubnetIp() { | ||
| 201 | + return subnetIp; | ||
| 202 | + } | ||
| 203 | + | ||
| 204 | + public void setSubnetIp(String subnetIp) { | ||
| 205 | + this.subnetIp = subnetIp; | ||
| 206 | + } | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | + /** | ||
| 210 | + * Returns the configured subnets for a segment router. | ||
| 211 | + * | ||
| 212 | + * @return list of subnets | ||
| 213 | + */ | ||
| 214 | + public List<Subnet> getSubnets() { | ||
| 215 | + return subnets; | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + public void setSubnets(List<Subnet> subnets) { | ||
| 219 | + this.subnets = subnets; | ||
| 220 | + } | ||
| 221 | + | ||
| 222 | + // ******************** | ||
| 223 | + // Helper methods | ||
| 224 | + // ******************** | ||
| 225 | + | ||
| 226 | + private void parseParams() { | ||
| 227 | + if (params == null) { | ||
| 228 | + throw new NetworkConfigException.ParamsNotSpecified(name); | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | + Set<Entry<String, JsonNode>> m = params.entrySet(); | ||
| 232 | + for (Entry<String, JsonNode> e : m) { | ||
| 233 | + String key = e.getKey(); | ||
| 234 | + JsonNode j = e.getValue(); | ||
| 235 | + if (key.equals("routerIp")) { | ||
| 236 | + setRouterIp(j.asText()); | ||
| 237 | + } else if (key.equals("routerMac")) { | ||
| 238 | + setRouterMac(j.asText()); | ||
| 239 | + } else if (key.equals("nodeSid")) { | ||
| 240 | + setNodeSid(j.asInt()); | ||
| 241 | + } else if (key.equals("isEdgeRouter")) { | ||
| 242 | + setIsEdgeRouter(j.asBoolean()); | ||
| 243 | + } else if (key.equals("adjacencySids") || key.equals("subnets")) { | ||
| 244 | + getInnerParams(j, key); | ||
| 245 | + } else { | ||
| 246 | + throw new UnknownSegmentRouterConfig(key, dpid); | ||
| 247 | + } | ||
| 248 | + } | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + private void getInnerParams(JsonNode j, String innerParam) { | ||
| 252 | + Iterator<JsonNode> innerList = j.elements(); | ||
| 253 | + while (innerList.hasNext()) { | ||
| 254 | + Iterator<Entry<String, JsonNode>> f = innerList.next().fields(); | ||
| 255 | + int portNo = -1; | ||
| 256 | + int adjSid = -1; | ||
| 257 | + String subnetIp = null; | ||
| 258 | + List<Integer> ports = null; | ||
| 259 | + while (f.hasNext()) { | ||
| 260 | + Entry<String, JsonNode> fe = f.next(); | ||
| 261 | + if (fe.getKey().equals("portNo")) { | ||
| 262 | + portNo = fe.getValue().asInt(); | ||
| 263 | + } else if (fe.getKey().equals("adjSid")) { | ||
| 264 | + adjSid = fe.getValue().asInt(); | ||
| 265 | + } else if (fe.getKey().equals("subnetIp")) { | ||
| 266 | + subnetIp = fe.getValue().asText(); | ||
| 267 | + } else if (fe.getKey().equals("ports")) { | ||
| 268 | + if (fe.getValue().isArray()) { | ||
| 269 | + Iterator<JsonNode> i = fe.getValue().elements(); | ||
| 270 | + ports = new ArrayList<Integer>(); | ||
| 271 | + while (i.hasNext()) { | ||
| 272 | + ports.add(i.next().asInt()); | ||
| 273 | + } | ||
| 274 | + } | ||
| 275 | + } else { | ||
| 276 | + throw new UnknownSegmentRouterConfig(fe.getKey(), dpid); | ||
| 277 | + } | ||
| 278 | + } | ||
| 279 | + if (innerParam.equals("adjacencySids")) { | ||
| 280 | + AdjacencySid ads = new AdjacencySid(adjSid, ports); | ||
| 281 | + adjacencySids.add(ads); | ||
| 282 | + } else { | ||
| 283 | + Subnet sip = new Subnet(portNo, subnetIp); | ||
| 284 | + subnets.add(sip); | ||
| 285 | + } | ||
| 286 | + } | ||
| 287 | + } | ||
| 288 | + | ||
| 289 | + private void validateParams() { | ||
| 290 | + if (routerIp == null) { | ||
| 291 | + throw new IpNotSpecified(dpid); | ||
| 292 | + } | ||
| 293 | + if (routerMac == null) { | ||
| 294 | + throw new MacNotSpecified(dpid); | ||
| 295 | + } | ||
| 296 | + if (isEdgeRouter && subnets.isEmpty()) { | ||
| 297 | + throw new SubnetNotSpecifiedInEdgeRouter(dpid); | ||
| 298 | + } | ||
| 299 | + if (!isEdgeRouter && !subnets.isEmpty()) { | ||
| 300 | + throw new SubnetSpecifiedInBackboneRouter(dpid); | ||
| 301 | + } | ||
| 302 | + if (nodeSid > SRGB_MAX) { | ||
| 303 | + throw new NodeLabelNotInSRGB(nodeSid, dpid); | ||
| 304 | + } | ||
| 305 | + for (AdjacencySid as : adjacencySids) { | ||
| 306 | + int label = as.getAdjSid(); | ||
| 307 | + List<Integer> plist = as.getPorts(); | ||
| 308 | + if (label <= SRGB_MAX) { | ||
| 309 | + throw new AdjacencyLabelInSRGB(label, dpid); | ||
| 310 | + } | ||
| 311 | + if (plist.size() <= 1) { | ||
| 312 | + throw new AdjacencyLabelNotEnoughPorts(label, dpid); | ||
| 313 | + } | ||
| 314 | + } | ||
| 315 | + | ||
| 316 | + | ||
| 317 | + // TODO more validations | ||
| 318 | + } | ||
| 319 | + | ||
| 320 | + /** | ||
| 321 | + * Setting publishAttributes implies that this is the configuration that | ||
| 322 | + * will be added to Topology.Switch object before it is published on the | ||
| 323 | + * channel to other controller instances. | ||
| 324 | + */ | ||
| 325 | + private void setPublishAttributes() { | ||
| 326 | + publishAttributes.put(ROUTER_IP, routerIp); | ||
| 327 | + publishAttributes.put(ROUTER_MAC, routerMac); | ||
| 328 | + publishAttributes.put(NODE_SID, String.valueOf(nodeSid)); | ||
| 329 | + publishAttributes.put(ISEDGE, String.valueOf(isEdgeRouter)); | ||
| 330 | + ObjectMapper mapper = new ObjectMapper(); | ||
| 331 | + try { | ||
| 332 | + publishAttributes.put(ADJACENCY_SIDS, | ||
| 333 | + mapper.writeValueAsString(adjacencySids)); | ||
| 334 | + publishAttributes.put(SUBNETS, | ||
| 335 | + mapper.writeValueAsString(subnets)); | ||
| 336 | + } catch (JsonProcessingException e) { | ||
| 337 | + log.error("Error while writing SR config: {}", e.getCause()); | ||
| 338 | + } catch (IOException e) { | ||
| 339 | + log.error("Error while writing SR config: {}", e.getCause()); | ||
| 340 | + } | ||
| 341 | + } | ||
| 342 | + | ||
| 343 | + // ******************** | ||
| 344 | + // Exceptions | ||
| 345 | + // ******************** | ||
| 346 | + | ||
| 347 | + public static class IpNotSpecified extends RuntimeException { | ||
| 348 | + private static final long serialVersionUID = -3001502553646331686L; | ||
| 349 | + | ||
| 350 | + public IpNotSpecified(DeviceId dpid) { | ||
| 351 | + super(); | ||
| 352 | + log.error("Router IP address not specified for SR config dpid:{}", | ||
| 353 | + dpid); | ||
| 354 | + } | ||
| 355 | + } | ||
| 356 | + | ||
| 357 | + public static class MacNotSpecified extends RuntimeException { | ||
| 358 | + private static final long serialVersionUID = -5850132094884129179L; | ||
| 359 | + | ||
| 360 | + public MacNotSpecified(DeviceId dpid) { | ||
| 361 | + super(); | ||
| 362 | + log.error("Router Mac address not specified for SR config dpid:{}", | ||
| 363 | + dpid); | ||
| 364 | + } | ||
| 365 | + } | ||
| 366 | + | ||
| 367 | + public static class UnknownSegmentRouterConfig extends RuntimeException { | ||
| 368 | + private static final long serialVersionUID = -5750132094884129179L; | ||
| 369 | + | ||
| 370 | + public UnknownSegmentRouterConfig(String key, DeviceId dpid) { | ||
| 371 | + super(); | ||
| 372 | + log.error("Unknown Segment Router config {} in dpid: {}", key, | ||
| 373 | + dpid); | ||
| 374 | + } | ||
| 375 | + } | ||
| 376 | + | ||
| 377 | + public static class SubnetNotSpecifiedInEdgeRouter extends RuntimeException { | ||
| 378 | + private static final long serialVersionUID = -5855458472668581268L; | ||
| 379 | + | ||
| 380 | + public SubnetNotSpecifiedInEdgeRouter(DeviceId dpid) { | ||
| 381 | + super(); | ||
| 382 | + log.error("Subnet was not specified for edge router in dpid: {}", | ||
| 383 | + dpid); | ||
| 384 | + } | ||
| 385 | + } | ||
| 386 | + | ||
| 387 | + public static class SubnetSpecifiedInBackboneRouter extends RuntimeException { | ||
| 388 | + private static final long serialVersionUID = 1L; | ||
| 389 | + | ||
| 390 | + public SubnetSpecifiedInBackboneRouter(DeviceId dpid) { | ||
| 391 | + super(); | ||
| 392 | + log.error("Subnet was specified in backbone router in dpid: {}", | ||
| 393 | + dpid); | ||
| 394 | + } | ||
| 395 | + } | ||
| 396 | + | ||
| 397 | + public static class NodeLabelNotInSRGB extends RuntimeException { | ||
| 398 | + private static final long serialVersionUID = -8482670903748519526L; | ||
| 399 | + | ||
| 400 | + public NodeLabelNotInSRGB(int label, DeviceId dpid) { | ||
| 401 | + super(); | ||
| 402 | + log.error("Node sif {} specified in not in global label-base " | ||
| 403 | + + "in dpid: {}", label, | ||
| 404 | + dpid); | ||
| 405 | + } | ||
| 406 | + } | ||
| 407 | + | ||
| 408 | + public static class AdjacencyLabelInSRGB extends RuntimeException { | ||
| 409 | + private static final long serialVersionUID = -8482670903748519526L; | ||
| 410 | + | ||
| 411 | + public AdjacencyLabelInSRGB(int label, DeviceId dpid) { | ||
| 412 | + super(); | ||
| 413 | + log.error("Adjaceny label {} specified from global label-base " | ||
| 414 | + + "in dpid: {}", label, | ||
| 415 | + dpid); | ||
| 416 | + } | ||
| 417 | + } | ||
| 418 | + | ||
| 419 | + public static class AdjacencyLabelNotEnoughPorts extends RuntimeException { | ||
| 420 | + private static final long serialVersionUID = -8482670903748519526L; | ||
| 421 | + | ||
| 422 | + public AdjacencyLabelNotEnoughPorts(int label, DeviceId dpid) { | ||
| 423 | + super(); | ||
| 424 | + log.error("Adjaceny label {} must be specified for at least 2 ports. " | ||
| 425 | + + "Adjacency labels for single ports are auto-generated " | ||
| 426 | + + "in dpid: {}", label, | ||
| 427 | + dpid); | ||
| 428 | + } | ||
| 429 | + } | ||
| 430 | +} |
| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | -package org.onosproject.grouphandler; | 16 | +package org.onosproject.segmentrouting.grouphandler; |
| 17 | 17 | ||
| 18 | import java.util.Arrays; | 18 | import java.util.Arrays; |
| 19 | import java.util.HashSet; | 19 | import java.util.HashSet; | ... | ... |
| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | -package org.onosproject.grouphandler; | 16 | +package org.onosproject.segmentrouting.grouphandler; |
| 17 | 17 | ||
| 18 | import static com.google.common.base.Preconditions.checkNotNull; | 18 | import static com.google.common.base.Preconditions.checkNotNull; |
| 19 | import static org.slf4j.LoggerFactory.getLogger; | 19 | import static org.slf4j.LoggerFactory.getLogger; | ... | ... |
| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | -package org.onosproject.grouphandler; | 16 | +package org.onosproject.segmentrouting.grouphandler; |
| 17 | 17 | ||
| 18 | import java.util.Arrays; | 18 | import java.util.Arrays; |
| 19 | import java.util.HashSet; | 19 | import java.util.HashSet; | ... | ... |
| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | -package org.onosproject.grouphandler; | 16 | +package org.onosproject.segmentrouting.grouphandler; |
| 17 | 17 | ||
| 18 | import java.util.List; | 18 | import java.util.List; |
| 19 | 19 | ... | ... |
| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | -package org.onosproject.grouphandler; | 16 | +package org.onosproject.segmentrouting.grouphandler; |
| 17 | 17 | ||
| 18 | import static com.google.common.base.Preconditions.checkNotNull; | 18 | import static com.google.common.base.Preconditions.checkNotNull; |
| 19 | 19 | ... | ... |
| ... | @@ -14,7 +14,7 @@ | ... | @@ -14,7 +14,7 @@ |
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | -package org.onosproject.grouphandler; | 17 | +package org.onosproject.segmentrouting.grouphandler; |
| 18 | 18 | ||
| 19 | import static com.google.common.base.Preconditions.checkNotNull; | 19 | import static com.google.common.base.Preconditions.checkNotNull; |
| 20 | 20 | ... | ... |
| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | -package org.onosproject.grouphandler; | 16 | +package org.onosproject.segmentrouting.grouphandler; |
| 17 | 17 | ||
| 18 | import static org.slf4j.LoggerFactory.getLogger; | 18 | import static org.slf4j.LoggerFactory.getLogger; |
| 19 | 19 | ||
| ... | @@ -26,7 +26,7 @@ import java.util.List; | ... | @@ -26,7 +26,7 @@ import java.util.List; |
| 26 | import org.onlab.packet.MplsLabel; | 26 | import org.onlab.packet.MplsLabel; |
| 27 | import org.onosproject.core.ApplicationId; | 27 | import org.onosproject.core.ApplicationId; |
| 28 | import org.onosproject.core.GroupId; | 28 | import org.onosproject.core.GroupId; |
| 29 | -import org.onosproject.grouphandler.GroupBucketIdentifier.BucketOutputType; | 29 | +import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType; |
| 30 | import org.onosproject.net.DeviceId; | 30 | import org.onosproject.net.DeviceId; |
| 31 | import org.onosproject.net.PortNumber; | 31 | import org.onosproject.net.PortNumber; |
| 32 | import org.onosproject.net.flow.DefaultTrafficTreatment; | 32 | import org.onosproject.net.flow.DefaultTrafficTreatment; | ... | ... |
| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | -package org.onosproject.grouphandler; | 16 | +package org.onosproject.segmentrouting.grouphandler; |
| 17 | 17 | ||
| 18 | import java.util.List; | 18 | import java.util.List; |
| 19 | 19 | ... | ... |
| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. | 14 | * limitations under the License. |
| 15 | */ | 15 | */ |
| 16 | -package org.onosproject.grouphandler; | 16 | +package org.onosproject.segmentrouting.grouphandler; |
| 17 | 17 | ||
| 18 | import static com.google.common.base.Preconditions.checkNotNull; | 18 | import static com.google.common.base.Preconditions.checkNotNull; |
| 19 | 19 | ... | ... |
| 1 | +{ | ||
| 2 | + "comment": " Multilayer topology description and configuration", | ||
| 3 | + "restrictSwitches": true, | ||
| 4 | + "restrictLinks": true, | ||
| 5 | + | ||
| 6 | + "switchConfig": | ||
| 7 | + [ | ||
| 8 | + { "nodeDpid" : "of:0000000000000001", "name": "Dallas-R1", "type": "Router_SR", "allowed": true, | ||
| 9 | + "latitude": 80.80, "longitude": 90.10, | ||
| 10 | + "params": { "routerIp": "192.168.0.1/32", | ||
| 11 | + "routerMac": "00:00:01:01:01:80", | ||
| 12 | + "nodeSid": 101, | ||
| 13 | + "isEdgeRouter" : true, | ||
| 14 | + "adjacencySids": [ | ||
| 15 | + { "ports": [ 4, 5 ], "adjSid": 10234 }, | ||
| 16 | + { "ports": [ 6, 7 ], "adjSid": 29019 } | ||
| 17 | + ], | ||
| 18 | + "subnets": [ | ||
| 19 | + { "portNo": 1, "subnetIp": "10.0.1.128/24" } | ||
| 20 | + ] | ||
| 21 | + } | ||
| 22 | + }, | ||
| 23 | + | ||
| 24 | + { "nodeDpid": "of:0000000000000002", "name": "Dallas-R2", "type": "Router_SR", "allowed": true, | ||
| 25 | + "latitude": 80.80, "longitude": 90.10, | ||
| 26 | + "params": { "routerIp": "192.168.0.2/32", | ||
| 27 | + "routerMac": "00:00:02:02:02:80", | ||
| 28 | + "nodeSid": 102, | ||
| 29 | + "isEdgeRouter" : false, | ||
| 30 | + "adjacencySids": [ | ||
| 31 | + { "ports": [ 1, 2 ], "adjSid": 12453 }, | ||
| 32 | + { "ports": [ 2, 3 ], "adjSid": 23333 }, | ||
| 33 | + { "ports": [ 3, 1 ], "adjSid": 22233 } | ||
| 34 | + ] | ||
| 35 | + } | ||
| 36 | + }, | ||
| 37 | + | ||
| 38 | + { "nodeDpid": "of:0000000000000003", "name": "Dallas-R3", "type": "Router_SR", "allowed": true, | ||
| 39 | + "latitude": 80.80, "longitude": 90.10, | ||
| 40 | + "params": { "routerIp": "192.168.0.3/32", | ||
| 41 | + "routerMac": "00:00:03:03:03:80", | ||
| 42 | + "nodeSid": 103, | ||
| 43 | + "isEdgeRouter" : false | ||
| 44 | + } | ||
| 45 | + }, | ||
| 46 | + | ||
| 47 | + { "nodeDpid": "of:0000000000000004", "name": "Dallas-R4", "type": "Router_SR", "allowed": true, | ||
| 48 | + "latitude": 80.80, "longitude": 90.10, | ||
| 49 | + "params": { "routerIp": "192.168.0.4/32", | ||
| 50 | + "routerMac": "00:00:04:04:04:80", | ||
| 51 | + "nodeSid": 104, | ||
| 52 | + "isEdgeRouter" : false | ||
| 53 | + } | ||
| 54 | + }, | ||
| 55 | + | ||
| 56 | + { "nodeDpid": "of:0000000000000005", "name": "Dallas-R5", "type": "Router_SR", "allowed": true, | ||
| 57 | + "latitude": 80.80, "longitude": 90.10, | ||
| 58 | + "params": { "routerIp": "192.168.0.5/32", | ||
| 59 | + "routerMac": "00:00:05:05:05:80", | ||
| 60 | + "nodeSid": 105, | ||
| 61 | + "isEdgeRouter" : false | ||
| 62 | + } | ||
| 63 | + }, | ||
| 64 | + | ||
| 65 | + { "nodeDpid": "of:0000000000000006", "name": "Dallas-R6", "type": "Router_SR", "allowed": true, | ||
| 66 | + "latitude": 80.80, "longitude": 90.10, | ||
| 67 | + "params": { "routerIp": "192.168.0.6/32", | ||
| 68 | + "routerMac": "00:00:07:07:07:80", | ||
| 69 | + "nodeSid": 106, | ||
| 70 | + "isEdgeRouter" : true, | ||
| 71 | + "subnets": [ | ||
| 72 | + { "portNo": 1, "subnetIp": "7.7.7.128/24" } | ||
| 73 | + ] | ||
| 74 | + } | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + ] | ||
| 78 | +} |
-
Please register or login to post a comment