Committed by
Gerrit Code Review
SR app now assigns internal vlans per subnet and passes this
information in a filtering objective to drivers. OF-DPA driver uses this information to assign vlans to untagged packets. Change-Id: Ibf33bdcedf5f83992f362dfb91c12575c65da3b4
Showing
5 changed files
with
273 additions
and
83 deletions
... | @@ -38,6 +38,7 @@ import java.util.HashMap; | ... | @@ -38,6 +38,7 @@ import java.util.HashMap; |
38 | import java.util.List; | 38 | import java.util.List; |
39 | import java.util.Map; | 39 | import java.util.Map; |
40 | import java.util.Set; | 40 | import java.util.Set; |
41 | +import java.util.concurrent.ConcurrentHashMap; | ||
41 | 42 | ||
42 | /** | 43 | /** |
43 | * Segment Routing configuration component that reads the | 44 | * Segment Routing configuration component that reads the |
... | @@ -51,7 +52,8 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -51,7 +52,8 @@ public class DeviceConfiguration implements DeviceProperties { |
51 | private static final Logger log = LoggerFactory | 52 | private static final Logger log = LoggerFactory |
52 | .getLogger(DeviceConfiguration.class); | 53 | .getLogger(DeviceConfiguration.class); |
53 | private final List<Integer> allSegmentIds = new ArrayList<>(); | 54 | private final List<Integer> allSegmentIds = new ArrayList<>(); |
54 | - private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>(); | 55 | + private final ConcurrentHashMap<DeviceId, SegmentRouterInfo> deviceConfigMap |
56 | + = new ConcurrentHashMap<>(); | ||
55 | 57 | ||
56 | private class SegmentRouterInfo { | 58 | private class SegmentRouterInfo { |
57 | int nodeSid; | 59 | int nodeSid; |
... | @@ -133,11 +135,10 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -133,11 +135,10 @@ public class DeviceConfiguration implements DeviceProperties { |
133 | */ | 135 | */ |
134 | @Override | 136 | @Override |
135 | public int getSegmentId(DeviceId deviceId) { | 137 | public int getSegmentId(DeviceId deviceId) { |
136 | - if (deviceConfigMap.get(deviceId) != null) { | 138 | + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); |
137 | - log.trace("getSegmentId for device{} is {}", | 139 | + if (srinfo != null) { |
138 | - deviceId, | 140 | + log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid); |
139 | - deviceConfigMap.get(deviceId).nodeSid); | 141 | + return srinfo.nodeSid; |
140 | - return deviceConfigMap.get(deviceId).nodeSid; | ||
141 | } else { | 142 | } else { |
142 | log.warn("getSegmentId for device {} " | 143 | log.warn("getSegmentId for device {} " |
143 | + "throwing IllegalStateException " | 144 | + "throwing IllegalStateException " |
... | @@ -150,7 +151,7 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -150,7 +151,7 @@ public class DeviceConfiguration implements DeviceProperties { |
150 | * Returns the Node segment id of a segment router given its Router mac address. | 151 | * Returns the Node segment id of a segment router given its Router mac address. |
151 | * | 152 | * |
152 | * @param routerMac router mac address | 153 | * @param routerMac router mac address |
153 | - * @return segment id | 154 | + * @return node segment id, or -1 if not found in config |
154 | */ | 155 | */ |
155 | public int getSegmentId(MacAddress routerMac) { | 156 | public int getSegmentId(MacAddress routerMac) { |
156 | for (Map.Entry<DeviceId, SegmentRouterInfo> entry: | 157 | for (Map.Entry<DeviceId, SegmentRouterInfo> entry: |
... | @@ -167,7 +168,7 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -167,7 +168,7 @@ public class DeviceConfiguration implements DeviceProperties { |
167 | * Returns the Node segment id of a segment router given its Router ip address. | 168 | * Returns the Node segment id of a segment router given its Router ip address. |
168 | * | 169 | * |
169 | * @param routerAddress router ip address | 170 | * @param routerAddress router ip address |
170 | - * @return segment id | 171 | + * @return node segment id, or -1 if not found in config |
171 | */ | 172 | */ |
172 | public int getSegmentId(Ip4Address routerAddress) { | 173 | public int getSegmentId(Ip4Address routerAddress) { |
173 | for (Map.Entry<DeviceId, SegmentRouterInfo> entry: | 174 | for (Map.Entry<DeviceId, SegmentRouterInfo> entry: |
... | @@ -188,11 +189,10 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -188,11 +189,10 @@ public class DeviceConfiguration implements DeviceProperties { |
188 | */ | 189 | */ |
189 | @Override | 190 | @Override |
190 | public MacAddress getDeviceMac(DeviceId deviceId) { | 191 | public MacAddress getDeviceMac(DeviceId deviceId) { |
191 | - if (deviceConfigMap.get(deviceId) != null) { | 192 | + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); |
192 | - log.trace("getDeviceMac for device{} is {}", | 193 | + if (srinfo != null) { |
193 | - deviceId, | 194 | + log.trace("getDeviceMac for device{} is {}", deviceId, srinfo.mac); |
194 | - deviceConfigMap.get(deviceId).mac); | 195 | + return srinfo.mac; |
195 | - return deviceConfigMap.get(deviceId).mac; | ||
196 | } else { | 196 | } else { |
197 | log.warn("getDeviceMac for device {} " | 197 | log.warn("getDeviceMac for device {} " |
198 | + "throwing IllegalStateException " | 198 | + "throwing IllegalStateException " |
... | @@ -208,11 +208,10 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -208,11 +208,10 @@ public class DeviceConfiguration implements DeviceProperties { |
208 | * @return router ip address | 208 | * @return router ip address |
209 | */ | 209 | */ |
210 | public Ip4Address getRouterIp(DeviceId deviceId) { | 210 | public Ip4Address getRouterIp(DeviceId deviceId) { |
211 | - if (deviceConfigMap.get(deviceId) != null) { | 211 | + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); |
212 | - log.trace("getDeviceIp for device{} is {}", | 212 | + if (srinfo != null) { |
213 | - deviceId, | 213 | + log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip); |
214 | - deviceConfigMap.get(deviceId).ip); | 214 | + return srinfo.ip; |
215 | - return deviceConfigMap.get(deviceId).ip; | ||
216 | } else { | 215 | } else { |
217 | log.warn("getRouterIp for device {} " | 216 | log.warn("getRouterIp for device {} " |
218 | + "throwing IllegalStateException " | 217 | + "throwing IllegalStateException " |
... | @@ -230,11 +229,10 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -230,11 +229,10 @@ public class DeviceConfiguration implements DeviceProperties { |
230 | */ | 229 | */ |
231 | @Override | 230 | @Override |
232 | public boolean isEdgeDevice(DeviceId deviceId) { | 231 | public boolean isEdgeDevice(DeviceId deviceId) { |
233 | - if (deviceConfigMap.get(deviceId) != null) { | 232 | + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); |
234 | - log.trace("isEdgeDevice for device{} is {}", | 233 | + if (srinfo != null) { |
235 | - deviceId, | 234 | + log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge); |
236 | - deviceConfigMap.get(deviceId).isEdge); | 235 | + return srinfo.isEdge; |
237 | - return deviceConfigMap.get(deviceId).isEdge; | ||
238 | } else { | 236 | } else { |
239 | log.warn("isEdgeDevice for device {} " | 237 | log.warn("isEdgeDevice for device {} " |
240 | + "throwing IllegalStateException " | 238 | + "throwing IllegalStateException " |
... | @@ -295,17 +293,16 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -295,17 +293,16 @@ public class DeviceConfiguration implements DeviceProperties { |
295 | * on those ports. | 293 | * on those ports. |
296 | * | 294 | * |
297 | * @param deviceId device identifier | 295 | * @param deviceId device identifier |
298 | - * @return list of ip addresses configured on the ports | 296 | + * @return list of ip addresses configured on the ports or null if not found |
299 | */ | 297 | */ |
300 | public List<Ip4Address> getPortIPs(DeviceId deviceId) { | 298 | public List<Ip4Address> getPortIPs(DeviceId deviceId) { |
301 | - if (deviceConfigMap.get(deviceId) != null) { | 299 | + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); |
302 | - log.trace("getSubnetGatewayIps for device{} is {}", | 300 | + if (srinfo != null) { |
303 | - deviceId, | 301 | + log.trace("getSubnetGatewayIps for device{} is {}", deviceId, |
304 | - deviceConfigMap.get(deviceId).gatewayIps.values()); | 302 | + srinfo.gatewayIps.values()); |
305 | - return new ArrayList<>(deviceConfigMap.get(deviceId).gatewayIps.values()); | 303 | + return new ArrayList<>(srinfo.gatewayIps.values()); |
306 | - } else { | ||
307 | - return null; | ||
308 | } | 304 | } |
305 | + return null; | ||
309 | } | 306 | } |
310 | 307 | ||
311 | /** | 308 | /** |
... | @@ -313,11 +310,12 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -313,11 +310,12 @@ public class DeviceConfiguration implements DeviceProperties { |
313 | * for a segment router. | 310 | * for a segment router. |
314 | * | 311 | * |
315 | * @param deviceId device identifier | 312 | * @param deviceId device identifier |
316 | - * @return map of port to gateway IP addresses | 313 | + * @return map of port to gateway IP addresses or null if not found |
317 | */ | 314 | */ |
318 | public Map<PortNumber, Ip4Address> getPortIPMap(DeviceId deviceId) { | 315 | public Map<PortNumber, Ip4Address> getPortIPMap(DeviceId deviceId) { |
319 | - if (deviceConfigMap.get(deviceId) != null) { | 316 | + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); |
320 | - return deviceConfigMap.get(deviceId).gatewayIps; | 317 | + if (srinfo != null) { |
318 | + return srinfo.gatewayIps; | ||
321 | } | 319 | } |
322 | return null; | 320 | return null; |
323 | } | 321 | } |
... | @@ -326,17 +324,32 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -326,17 +324,32 @@ public class DeviceConfiguration implements DeviceProperties { |
326 | * Returns the configured subnet prefixes for a segment router. | 324 | * Returns the configured subnet prefixes for a segment router. |
327 | * | 325 | * |
328 | * @param deviceId device identifier | 326 | * @param deviceId device identifier |
329 | - * @return list of ip prefixes | 327 | + * @return list of ip prefixes or null if not found |
330 | */ | 328 | */ |
331 | public List<Ip4Prefix> getSubnets(DeviceId deviceId) { | 329 | public List<Ip4Prefix> getSubnets(DeviceId deviceId) { |
332 | - if (deviceConfigMap.get(deviceId) != null) { | 330 | + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); |
333 | - log.trace("getSubnets for device{} is {}", | 331 | + if (srinfo != null) { |
334 | - deviceId, | 332 | + log.trace("getSubnets for device{} is {}", deviceId, |
335 | - deviceConfigMap.get(deviceId).subnets.values()); | 333 | + srinfo.subnets.values()); |
336 | - return new ArrayList<>(deviceConfigMap.get(deviceId).subnets.values()); | 334 | + return new ArrayList<>(srinfo.subnets.values()); |
337 | - } else { | 335 | + } |
338 | - return null; | 336 | + return null; |
337 | + } | ||
338 | + | ||
339 | + /** | ||
340 | + * Returns the configured subnet on the given port, or null if no | ||
341 | + * subnet has been configured on the port. | ||
342 | + * | ||
343 | + * @param deviceId device identifier | ||
344 | + * @param pnum port identifier | ||
345 | + * @return configured subnet on port, or null | ||
346 | + */ | ||
347 | + public Ip4Prefix getPortSubnet(DeviceId deviceId, PortNumber pnum) { | ||
348 | + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); | ||
349 | + if (srinfo != null) { | ||
350 | + return srinfo.subnets.get(pnum); | ||
339 | } | 351 | } |
352 | + return null; | ||
340 | } | 353 | } |
341 | 354 | ||
342 | /** | 355 | /** |
... | @@ -365,7 +378,7 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -365,7 +378,7 @@ public class DeviceConfiguration implements DeviceProperties { |
365 | * specified ip address as one of its subnet gateway ip address. | 378 | * specified ip address as one of its subnet gateway ip address. |
366 | * | 379 | * |
367 | * @param gatewayIpAddress router gateway ip address | 380 | * @param gatewayIpAddress router gateway ip address |
368 | - * @return router mac address | 381 | + * @return router mac address or null if not found |
369 | */ | 382 | */ |
370 | public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) { | 383 | public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) { |
371 | for (Map.Entry<DeviceId, SegmentRouterInfo> entry: | 384 | for (Map.Entry<DeviceId, SegmentRouterInfo> entry: |
... | @@ -415,8 +428,9 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -415,8 +428,9 @@ public class DeviceConfiguration implements DeviceProperties { |
415 | * @return list of port numbers | 428 | * @return list of port numbers |
416 | */ | 429 | */ |
417 | public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) { | 430 | public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) { |
418 | - if (deviceConfigMap.get(deviceId) != null) { | 431 | + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); |
419 | - for (AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) { | 432 | + if (srinfo != null) { |
433 | + for (AdjacencySid asid : srinfo.adjacencySids) { | ||
420 | if (asid.getAsid() == sid) { | 434 | if (asid.getAsid() == sid) { |
421 | return asid.getPorts(); | 435 | return asid.getPorts(); |
422 | } | 436 | } |
... | @@ -435,12 +449,13 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -435,12 +449,13 @@ public class DeviceConfiguration implements DeviceProperties { |
435 | * otherwise false | 449 | * otherwise false |
436 | */ | 450 | */ |
437 | public boolean isAdjacencySid(DeviceId deviceId, int sid) { | 451 | public boolean isAdjacencySid(DeviceId deviceId, int sid) { |
438 | - if (deviceConfigMap.get(deviceId) != null) { | 452 | + SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); |
439 | - if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) { | 453 | + if (srinfo != null) { |
454 | + if (srinfo.adjacencySids.isEmpty()) { | ||
440 | return false; | 455 | return false; |
441 | } else { | 456 | } else { |
442 | for (AdjacencySid asid: | 457 | for (AdjacencySid asid: |
443 | - deviceConfigMap.get(deviceId).adjacencySids) { | 458 | + srinfo.adjacencySids) { |
444 | if (asid.getAsid() == sid) { | 459 | if (asid.getAsid() == sid) { |
445 | return true; | 460 | return true; |
446 | } | 461 | } | ... | ... |
... | @@ -25,6 +25,7 @@ import org.onlab.packet.VlanId; | ... | @@ -25,6 +25,7 @@ import org.onlab.packet.VlanId; |
25 | import org.onosproject.segmentrouting.grouphandler.NeighborSet; | 25 | import org.onosproject.segmentrouting.grouphandler.NeighborSet; |
26 | import org.onosproject.net.DeviceId; | 26 | import org.onosproject.net.DeviceId; |
27 | import org.onosproject.net.Link; | 27 | import org.onosproject.net.Link; |
28 | +import org.onosproject.net.Port; | ||
28 | import org.onosproject.net.PortNumber; | 29 | import org.onosproject.net.PortNumber; |
29 | import org.onosproject.net.flow.DefaultTrafficSelector; | 30 | import org.onosproject.net.flow.DefaultTrafficSelector; |
30 | import org.onosproject.net.flow.DefaultTrafficTreatment; | 31 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
... | @@ -60,6 +61,8 @@ public class RoutingRulePopulator { | ... | @@ -60,6 +61,8 @@ public class RoutingRulePopulator { |
60 | private DeviceConfiguration config; | 61 | private DeviceConfiguration config; |
61 | 62 | ||
62 | private static final int HIGHEST_PRIORITY = 0xffff; | 63 | private static final int HIGHEST_PRIORITY = 0xffff; |
64 | + private static final long OFPP_MAX = 0xffffff00L; | ||
65 | + | ||
63 | 66 | ||
64 | /** | 67 | /** |
65 | * Creates a RoutingRulePopulator object. | 68 | * Creates a RoutingRulePopulator object. |
... | @@ -355,25 +358,37 @@ public class RoutingRulePopulator { | ... | @@ -355,25 +358,37 @@ public class RoutingRulePopulator { |
355 | 358 | ||
356 | /** | 359 | /** |
357 | * Creates a filtering objective to permit all untagged packets with a | 360 | * Creates a filtering objective to permit all untagged packets with a |
358 | - * dstMac corresponding to the router's MAC address. | 361 | + * dstMac corresponding to the router's MAC address. For those pipelines |
362 | + * that need to internally assign vlans to untagged packets, this method | ||
363 | + * provides per-subnet vlan-ids as metadata. | ||
359 | * | 364 | * |
360 | * @param deviceId the switch dpid for the router | 365 | * @param deviceId the switch dpid for the router |
361 | */ | 366 | */ |
362 | public void populateRouterMacVlanFilters(DeviceId deviceId) { | 367 | public void populateRouterMacVlanFilters(DeviceId deviceId) { |
363 | - FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); | 368 | + log.debug("Installing per-port filtering objective for untagged " |
364 | - fob.withKey(Criteria.matchInPort(PortNumber.ALL)) | 369 | + + "packets in device {}", deviceId); |
370 | + for (Port port : srManager.deviceService.getPorts(deviceId)) { | ||
371 | + if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) { | ||
372 | + Ip4Prefix portSubnet = config.getPortSubnet(deviceId, port.number()); | ||
373 | + VlanId assignedVlan = (portSubnet == null) | ||
374 | + ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET) | ||
375 | + : srManager.getSubnetAssignedVlanId(deviceId, portSubnet); | ||
376 | + TrafficTreatment tt = DefaultTrafficTreatment.builder() | ||
377 | + .pushVlan().setVlanId(assignedVlan).build(); | ||
378 | + FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); | ||
379 | + fob.withKey(Criteria.matchInPort(port.number())) | ||
365 | .addCondition(Criteria.matchEthDst(config.getDeviceMac(deviceId))) | 380 | .addCondition(Criteria.matchEthDst(config.getDeviceMac(deviceId))) |
366 | .addCondition(Criteria.matchVlanId(VlanId.NONE)) | 381 | .addCondition(Criteria.matchVlanId(VlanId.NONE)) |
367 | - .addCondition(Criteria.matchIPDst( | 382 | + .setMeta(tt) |
368 | - IpPrefix.valueOf(config.getRouterIp(deviceId), | 383 | + .addCondition(Criteria.matchIPDst(IpPrefix.valueOf( |
369 | - IpPrefix.MAX_INET_MASK_LENGTH))); | 384 | + config.getRouterIp(deviceId), |
370 | - | 385 | + IpPrefix.MAX_INET_MASK_LENGTH))); |
371 | - fob.permit().fromApp(srManager.appId); | 386 | + fob.permit().fromApp(srManager.appId); |
372 | - log.debug("Installing filtering objective for untagged packets"); | 387 | + srManager.flowObjectiveService. |
373 | - srManager.flowObjectiveService. | 388 | + filter(deviceId, fob.add(new SRObjectiveContext(deviceId, |
374 | - filter(deviceId, | 389 | + SRObjectiveContext.ObjectiveType.FILTER))); |
375 | - fob.add(new SRObjectiveContext(deviceId, | 390 | + } |
376 | - SRObjectiveContext.ObjectiveType.FILTER))); | 391 | + } |
377 | } | 392 | } |
378 | 393 | ||
379 | /** | 394 | /** | ... | ... |
... | @@ -23,6 +23,8 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; | ... | @@ -23,6 +23,8 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; |
23 | import org.apache.felix.scr.annotations.Service; | 23 | import org.apache.felix.scr.annotations.Service; |
24 | import org.onlab.packet.Ethernet; | 24 | import org.onlab.packet.Ethernet; |
25 | import org.onlab.packet.IPv4; | 25 | import org.onlab.packet.IPv4; |
26 | +import org.onlab.packet.Ip4Prefix; | ||
27 | +import org.onlab.packet.VlanId; | ||
26 | import org.onlab.util.KryoNamespace; | 28 | import org.onlab.util.KryoNamespace; |
27 | import org.onosproject.core.ApplicationId; | 29 | import org.onosproject.core.ApplicationId; |
28 | import org.onosproject.core.CoreService; | 30 | import org.onosproject.core.CoreService; |
... | @@ -45,7 +47,6 @@ import org.onosproject.net.device.DeviceEvent; | ... | @@ -45,7 +47,6 @@ import org.onosproject.net.device.DeviceEvent; |
45 | import org.onosproject.net.device.DeviceListener; | 47 | import org.onosproject.net.device.DeviceListener; |
46 | import org.onosproject.net.device.DeviceService; | 48 | import org.onosproject.net.device.DeviceService; |
47 | import org.onosproject.net.flowobjective.FlowObjectiveService; | 49 | import org.onosproject.net.flowobjective.FlowObjectiveService; |
48 | -import org.onosproject.net.group.GroupKey; | ||
49 | import org.onosproject.net.host.HostService; | 50 | import org.onosproject.net.host.HostService; |
50 | import org.onosproject.net.intent.IntentService; | 51 | import org.onosproject.net.intent.IntentService; |
51 | import org.onosproject.net.link.LinkEvent; | 52 | import org.onosproject.net.link.LinkEvent; |
... | @@ -64,9 +65,11 @@ import org.slf4j.Logger; | ... | @@ -64,9 +65,11 @@ import org.slf4j.Logger; |
64 | import org.slf4j.LoggerFactory; | 65 | import org.slf4j.LoggerFactory; |
65 | 66 | ||
66 | import java.net.URI; | 67 | import java.net.URI; |
68 | +import java.util.Collections; | ||
67 | import java.util.HashSet; | 69 | import java.util.HashSet; |
68 | import java.util.List; | 70 | import java.util.List; |
69 | import java.util.Map; | 71 | import java.util.Map; |
72 | +import java.util.Set; | ||
70 | import java.util.concurrent.ConcurrentHashMap; | 73 | import java.util.concurrent.ConcurrentHashMap; |
71 | import java.util.concurrent.ConcurrentLinkedQueue; | 74 | import java.util.concurrent.ConcurrentLinkedQueue; |
72 | import java.util.concurrent.Executors; | 75 | import java.util.concurrent.Executors; |
... | @@ -135,6 +138,10 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -135,6 +138,10 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
135 | Integer> nsNextObjStore = null; | 138 | Integer> nsNextObjStore = null; |
136 | private EventuallyConsistentMap<String, Tunnel> tunnelStore = null; | 139 | private EventuallyConsistentMap<String, Tunnel> tunnelStore = null; |
137 | private EventuallyConsistentMap<String, Policy> policyStore = null; | 140 | private EventuallyConsistentMap<String, Policy> policyStore = null; |
141 | + // Per device, per-subnet assigned-vlans store, with (device id + subnet | ||
142 | + // IPv4 prefix) as key | ||
143 | + private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId> | ||
144 | + subnetVidStore = null; | ||
138 | 145 | ||
139 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 146 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
140 | protected StorageService storageService; | 147 | protected StorageService storageService; |
... | @@ -163,6 +170,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -163,6 +170,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
163 | 170 | ||
164 | private KryoNamespace.Builder kryoBuilder = null; | 171 | private KryoNamespace.Builder kryoBuilder = null; |
165 | 172 | ||
173 | + private static final short ASSIGNED_VLAN_START = 4093; | ||
174 | + public static final short ASSIGNED_VLAN_NO_SUBNET = 4094; | ||
175 | + | ||
166 | @Activate | 176 | @Activate |
167 | protected void activate() { | 177 | protected void activate() { |
168 | appId = coreService | 178 | appId = coreService |
... | @@ -180,7 +190,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -180,7 +190,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
180 | DefaultTunnel.class, | 190 | DefaultTunnel.class, |
181 | Policy.class, | 191 | Policy.class, |
182 | TunnelPolicy.class, | 192 | TunnelPolicy.class, |
183 | - Policy.Type.class | 193 | + Policy.Type.class, |
194 | + SubnetAssignedVidStoreKey.class, | ||
195 | + VlanId.class | ||
184 | ); | 196 | ); |
185 | 197 | ||
186 | log.debug("Creating EC map nsnextobjectivestore"); | 198 | log.debug("Creating EC map nsnextobjectivestore"); |
... | @@ -212,6 +224,15 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -212,6 +224,15 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
212 | .withTimestampProvider((k, v) -> new WallClockTimestamp()) | 224 | .withTimestampProvider((k, v) -> new WallClockTimestamp()) |
213 | .build(); | 225 | .build(); |
214 | 226 | ||
227 | + EventuallyConsistentMapBuilder<SubnetAssignedVidStoreKey, VlanId> | ||
228 | + subnetVidStoreMapBuilder = storageService.eventuallyConsistentMapBuilder(); | ||
229 | + | ||
230 | + subnetVidStore = subnetVidStoreMapBuilder | ||
231 | + .withName("subnetvidstore") | ||
232 | + .withSerializer(kryoBuilder) | ||
233 | + .withTimestampProvider((k, v) -> new WallClockTimestamp()) | ||
234 | + .build(); | ||
235 | + | ||
215 | cfgService.addListener(cfgListener); | 236 | cfgService.addListener(cfgListener); |
216 | cfgService.registerConfigFactory(cfgFactory); | 237 | cfgService.registerConfigFactory(cfgFactory); |
217 | 238 | ||
... | @@ -296,23 +317,72 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -296,23 +317,72 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
296 | } | 317 | } |
297 | 318 | ||
298 | /** | 319 | /** |
299 | - * Returns the GroupKey object for the device and the NeighborSet given. | 320 | + * Returns the vlan-id assigned to the subnet configured for a device. |
300 | - * XXX is this called | 321 | + * If no vlan-id has been assigned, a new one is assigned out of a pool of ids, |
322 | + * if and only if this controller instance is the master for the device. | ||
323 | + * <p> | ||
324 | + * USAGE: The assigned vlans are meant to be applied to untagged packets on those | ||
325 | + * switches/pipelines that need this functionality. These vids are meant | ||
326 | + * to be used internally within a switch, and thus need to be unique only | ||
327 | + * on a switch level. Note that packets never go out on the wire with these | ||
328 | + * vlans. Currently, vlan ids are assigned from value 4093 down. | ||
329 | + * Vlan id 4094 expected to be used for all ports that are not assigned subnets. | ||
330 | + * Vlan id 4095 is reserved and unused. Only a single vlan id is assigned | ||
331 | + * per subnet. | ||
332 | + * XXX This method should avoid any vlans configured on the ports, but | ||
333 | + * currently the app works only on untagged packets and as a result | ||
334 | + * ignores any vlan configuration. | ||
301 | * | 335 | * |
302 | - * @param ns NeightborSet object for the GroupKey | 336 | + * @param deviceId switch dpid |
303 | - * @return GroupKey object for the NeighborSet | 337 | + * @param subnet IPv4 prefix for which assigned vlan is desired |
338 | + * @return VlanId assigned for the subnet on the device, or | ||
339 | + * null if no vlan assignment was found and this instance is not | ||
340 | + * the master for the device. | ||
304 | */ | 341 | */ |
305 | - public GroupKey getGroupKey(NeighborSet ns) { | 342 | + public VlanId getSubnetAssignedVlanId(DeviceId deviceId, Ip4Prefix subnet) { |
306 | - for (DefaultGroupHandler groupHandler : groupHandlerMap.values()) { | 343 | + VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey( |
307 | - return groupHandler.getGroupKey(ns); | 344 | + deviceId, subnet)); |
345 | + if (assignedVid != null) { | ||
346 | + log.debug("Query for subnet:{} on device:{} returned assigned-vlan " | ||
347 | + + "{}", subnet, deviceId, assignedVid); | ||
348 | + return assignedVid; | ||
349 | + } | ||
350 | + //check mastership for the right to assign a vlan | ||
351 | + if (!mastershipService.isLocalMaster(deviceId)) { | ||
352 | + log.warn("This controller instance is not the master for device {}. " | ||
353 | + + "Cannot assign vlan-id for subnet {}", deviceId, subnet); | ||
354 | + return null; | ||
355 | + } | ||
356 | + // vlan assignment is expensive but done only once | ||
357 | + List<Ip4Prefix> configuredSubnets = deviceConfiguration.getSubnets(deviceId); | ||
358 | + Set<Short> assignedVlans = new HashSet<>(); | ||
359 | + Set<Ip4Prefix> unassignedSubnets = new HashSet<>(); | ||
360 | + for (Ip4Prefix sub : configuredSubnets) { | ||
361 | + VlanId v = subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId, | ||
362 | + sub)); | ||
363 | + if (v != null) { | ||
364 | + assignedVlans.add(v.toShort()); | ||
365 | + } else { | ||
366 | + unassignedSubnets.add(sub); | ||
367 | + } | ||
368 | + } | ||
369 | + short nextAssignedVlan = ASSIGNED_VLAN_START; | ||
370 | + if (!assignedVlans.isEmpty()) { | ||
371 | + nextAssignedVlan = (short) (Collections.min(assignedVlans) - 1); | ||
372 | + } | ||
373 | + for (Ip4Prefix unsub : unassignedSubnets) { | ||
374 | + subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub), | ||
375 | + VlanId.vlanId(nextAssignedVlan--)); | ||
376 | + log.info("Assigned vlan: {} to subnet: {} on device: {}", | ||
377 | + nextAssignedVlan + 1, unsub, deviceId); | ||
308 | } | 378 | } |
309 | 379 | ||
310 | - return null; | 380 | + return subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId, subnet)); |
311 | } | 381 | } |
312 | 382 | ||
313 | /** | 383 | /** |
314 | - * Returns the next objective ID for the NeighborSet given. If the nextObjectiveID does not exist, | 384 | + * Returns the next objective ID for the given NeighborSet. |
315 | - * a new one is created and returned. | 385 | + * If the nextObjectiveID does not exist, a new one is created and returned. |
316 | * | 386 | * |
317 | * @param deviceId Device ID | 387 | * @param deviceId Device ID |
318 | * @param ns NegighborSet | 388 | * @param ns NegighborSet | ... | ... |
apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SubnetAssignedVidStoreKey.java
0 → 100644
1 | +package org.onosproject.segmentrouting; | ||
2 | + | ||
3 | +import java.util.Objects; | ||
4 | + | ||
5 | +import org.onlab.packet.Ip4Prefix; | ||
6 | +import org.onosproject.net.DeviceId; | ||
7 | + | ||
8 | +/** | ||
9 | + * Class definition for key used to map per device subnets to assigned Vlan ids. | ||
10 | + * | ||
11 | + */ | ||
12 | +public class SubnetAssignedVidStoreKey { | ||
13 | + private final DeviceId deviceId; | ||
14 | + private final Ip4Prefix subnet; | ||
15 | + | ||
16 | + public SubnetAssignedVidStoreKey(DeviceId deviceId, Ip4Prefix subnet) { | ||
17 | + this.deviceId = deviceId; | ||
18 | + this.subnet = subnet; | ||
19 | + } | ||
20 | + | ||
21 | + /** | ||
22 | + * Returns the device identification used to create this key. | ||
23 | + * | ||
24 | + * @return the device identifier | ||
25 | + */ | ||
26 | + public DeviceId deviceId() { | ||
27 | + return deviceId; | ||
28 | + } | ||
29 | + | ||
30 | + /** | ||
31 | + * Returns the subnet information used to create this key. | ||
32 | + * | ||
33 | + * @return the subnet | ||
34 | + */ | ||
35 | + public Ip4Prefix subnet() { | ||
36 | + return subnet; | ||
37 | + } | ||
38 | + | ||
39 | + @Override | ||
40 | + public boolean equals(Object o) { | ||
41 | + if (this == o) { | ||
42 | + return true; | ||
43 | + } | ||
44 | + if (!(o instanceof SubnetAssignedVidStoreKey)) { | ||
45 | + return false; | ||
46 | + } | ||
47 | + SubnetAssignedVidStoreKey that = | ||
48 | + (SubnetAssignedVidStoreKey) o; | ||
49 | + return (Objects.equals(this.deviceId, that.deviceId) && | ||
50 | + Objects.equals(this.subnet, that.subnet)); | ||
51 | + } | ||
52 | + | ||
53 | + @Override | ||
54 | + public int hashCode() { | ||
55 | + int result = 17; | ||
56 | + result = 31 * result + Objects.hashCode(deviceId) | ||
57 | + + Objects.hashCode(subnet); | ||
58 | + return result; | ||
59 | + } | ||
60 | + | ||
61 | + @Override | ||
62 | + public String toString() { | ||
63 | + return "Device: " + deviceId + " Subnet: " + subnet; | ||
64 | + } | ||
65 | + | ||
66 | +} |
... | @@ -148,12 +148,6 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -148,12 +148,6 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
148 | //private static final int MPLSINTERFACEMASK = 0x90000000; | 148 | //private static final int MPLSINTERFACEMASK = 0x90000000; |
149 | private static final int L3ECMPMASK = 0x70000000; | 149 | private static final int L3ECMPMASK = 0x70000000; |
150 | 150 | ||
151 | - /* | ||
152 | - * This driver assigns all incoming untagged packets the same VLAN ID | ||
153 | - */ | ||
154 | - private static final short UNTAGGED_ASSIGNED_VLAN = 0xffa; // 4090 | ||
155 | - | ||
156 | - | ||
157 | private final Logger log = getLogger(getClass()); | 151 | private final Logger log = getLogger(getClass()); |
158 | private ServiceDirectory serviceDirectory; | 152 | private ServiceDirectory serviceDirectory; |
159 | protected FlowRuleService flowRuleService; | 153 | protected FlowRuleService flowRuleService; |
... | @@ -351,11 +345,35 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -351,11 +345,35 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
351 | } | 345 | } |
352 | } | 346 | } |
353 | 347 | ||
348 | + VlanId assignedVlan = null; | ||
349 | + if (vidCriterion != null && vidCriterion.vlanId() == VlanId.NONE) { | ||
350 | + // untagged packets are assigned vlans in OF-DPA | ||
351 | + if (filt.meta() == null) { | ||
352 | + log.error("Missing metadata in filtering objective required " | ||
353 | + + "for vlan assignment in dev {}", deviceId); | ||
354 | + fail(filt, ObjectiveError.BADPARAMS); | ||
355 | + return; | ||
356 | + } | ||
357 | + for (Instruction i : filt.meta().allInstructions()) { | ||
358 | + if (i instanceof ModVlanIdInstruction) { | ||
359 | + assignedVlan = ((ModVlanIdInstruction) i).vlanId(); | ||
360 | + } | ||
361 | + } | ||
362 | + if (assignedVlan == null) { | ||
363 | + log.error("Driver requires an assigned vlan-id to tag incoming " | ||
364 | + + "untagged packets. Not processing vlan filters on " | ||
365 | + + "device {}", deviceId); | ||
366 | + fail(filt, ObjectiveError.BADPARAMS); | ||
367 | + return; | ||
368 | + } | ||
369 | + } | ||
370 | + | ||
354 | if (ethCriterion == null) { | 371 | if (ethCriterion == null) { |
355 | log.debug("filtering objective missing dstMac, cannot program TMAC table"); | 372 | log.debug("filtering objective missing dstMac, cannot program TMAC table"); |
356 | } else { | 373 | } else { |
357 | for (FlowRule tmacRule : processEthDstFilter(portCriterion, ethCriterion, | 374 | for (FlowRule tmacRule : processEthDstFilter(portCriterion, ethCriterion, |
358 | - vidCriterion, applicationId)) { | 375 | + vidCriterion, assignedVlan, |
376 | + applicationId)) { | ||
359 | log.debug("adding MAC filtering rules in TMAC table: {} for dev: {}", | 377 | log.debug("adding MAC filtering rules in TMAC table: {} for dev: {}", |
360 | tmacRule, deviceId); | 378 | tmacRule, deviceId); |
361 | ops = install ? ops.add(tmacRule) : ops.remove(tmacRule); | 379 | ops = install ? ops.add(tmacRule) : ops.remove(tmacRule); |
... | @@ -367,6 +385,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -367,6 +385,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
367 | + "Vlan Table"); | 385 | + "Vlan Table"); |
368 | } else { | 386 | } else { |
369 | for (FlowRule vlanRule : processVlanIdFilter(portCriterion, vidCriterion, | 387 | for (FlowRule vlanRule : processVlanIdFilter(portCriterion, vidCriterion, |
388 | + assignedVlan, | ||
370 | applicationId)) { | 389 | applicationId)) { |
371 | log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}", | 390 | log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}", |
372 | vlanRule, deviceId); | 391 | vlanRule, deviceId); |
... | @@ -419,14 +438,18 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -419,14 +438,18 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
419 | 438 | ||
420 | /** | 439 | /** |
421 | * Allows untagged packets into pipeline by assigning a vlan id. | 440 | * Allows untagged packets into pipeline by assigning a vlan id. |
441 | + * Vlan assignment is done by the application. | ||
422 | * Allows tagged packets into pipeline as per configured port-vlan info. | 442 | * Allows tagged packets into pipeline as per configured port-vlan info. |
443 | + * | ||
423 | * @param portCriterion port on device for which this filter is programmed | 444 | * @param portCriterion port on device for which this filter is programmed |
424 | * @param vidCriterion vlan assigned to port, or NONE for untagged | 445 | * @param vidCriterion vlan assigned to port, or NONE for untagged |
446 | + * @param assignedVlan assigned vlan-id for untagged packets | ||
425 | * @param applicationId for application programming this filter | 447 | * @param applicationId for application programming this filter |
426 | * @return list of FlowRule for port-vlan filters | 448 | * @return list of FlowRule for port-vlan filters |
427 | */ | 449 | */ |
428 | protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion, | 450 | protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion, |
429 | VlanIdCriterion vidCriterion, | 451 | VlanIdCriterion vidCriterion, |
452 | + VlanId assignedVlan, | ||
430 | ApplicationId applicationId) { | 453 | ApplicationId applicationId) { |
431 | List<FlowRule> rules = new ArrayList<FlowRule>(); | 454 | List<FlowRule> rules = new ArrayList<FlowRule>(); |
432 | TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | 455 | TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
... | @@ -434,7 +457,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -434,7 +457,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
434 | selector.matchVlanId(vidCriterion.vlanId()); | 457 | selector.matchVlanId(vidCriterion.vlanId()); |
435 | if (vidCriterion.vlanId() == VlanId.NONE) { | 458 | if (vidCriterion.vlanId() == VlanId.NONE) { |
436 | // untagged packets are assigned vlans | 459 | // untagged packets are assigned vlans |
437 | - treatment.pushVlan().setVlanId(VlanId.vlanId(UNTAGGED_ASSIGNED_VLAN)); | 460 | + treatment.pushVlan().setVlanId(assignedVlan); |
438 | // XXX ofdpa may require an additional vlan match on the assigned vlan | 461 | // XXX ofdpa may require an additional vlan match on the assigned vlan |
439 | // and it may not require the push. | 462 | // and it may not require the push. |
440 | } | 463 | } |
... | @@ -475,6 +498,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -475,6 +498,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
475 | * @param portCriterion port on device for which this filter is programmed | 498 | * @param portCriterion port on device for which this filter is programmed |
476 | * @param ethCriterion dstMac of device for which is filter is programmed | 499 | * @param ethCriterion dstMac of device for which is filter is programmed |
477 | * @param vidCriterion vlan assigned to port, or NONE for untagged | 500 | * @param vidCriterion vlan assigned to port, or NONE for untagged |
501 | + * @param assignedVlan assigned vlan-id for untagged packets | ||
478 | * @param applicationId for application programming this filter | 502 | * @param applicationId for application programming this filter |
479 | * @return list of FlowRule for port-vlan filters | 503 | * @return list of FlowRule for port-vlan filters |
480 | 504 | ||
... | @@ -482,11 +506,11 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -482,11 +506,11 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
482 | protected List<FlowRule> processEthDstFilter(PortCriterion portCriterion, | 506 | protected List<FlowRule> processEthDstFilter(PortCriterion portCriterion, |
483 | EthCriterion ethCriterion, | 507 | EthCriterion ethCriterion, |
484 | VlanIdCriterion vidCriterion, | 508 | VlanIdCriterion vidCriterion, |
509 | + VlanId assignedVlan, | ||
485 | ApplicationId applicationId) { | 510 | ApplicationId applicationId) { |
486 | //handling untagged packets via assigned VLAN | 511 | //handling untagged packets via assigned VLAN |
487 | if (vidCriterion.vlanId() == VlanId.NONE) { | 512 | if (vidCriterion.vlanId() == VlanId.NONE) { |
488 | - vidCriterion = (VlanIdCriterion) Criteria | 513 | + vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan); |
489 | - .matchVlanId(VlanId.vlanId(UNTAGGED_ASSIGNED_VLAN)); | ||
490 | } | 514 | } |
491 | // ofdpa cannot match on ALL portnumber, so we need to use separate | 515 | // ofdpa cannot match on ALL portnumber, so we need to use separate |
492 | // rules for each port. | 516 | // rules for each port. | ... | ... |
-
Please register or login to post a comment