Phaneendra Manda
Committed by Thomas Vachuska

[ONOS-3833] Identify the port chain for the packet

Change-Id: Id2ca1373588c8bc77c031149c7e85337c776bc4b
...@@ -17,6 +17,8 @@ package org.onosproject.sfc.manager.impl; ...@@ -17,6 +17,8 @@ package org.onosproject.sfc.manager.impl;
17 17
18 import static org.slf4j.LoggerFactory.getLogger; 18 import static org.slf4j.LoggerFactory.getLogger;
19 19
20 +import java.util.Collection;
21 +import java.util.Set;
20 import java.util.concurrent.ConcurrentHashMap; 22 import java.util.concurrent.ConcurrentHashMap;
21 import java.util.concurrent.ConcurrentMap; 23 import java.util.concurrent.ConcurrentMap;
22 24
...@@ -28,15 +30,16 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -28,15 +30,16 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
28 import org.apache.felix.scr.annotations.Service; 30 import org.apache.felix.scr.annotations.Service;
29 import org.onlab.packet.Ethernet; 31 import org.onlab.packet.Ethernet;
30 import org.onlab.packet.IPv4; 32 import org.onlab.packet.IPv4;
31 -import org.onlab.packet.IPv6;
32 import org.onlab.packet.IpAddress; 33 import org.onlab.packet.IpAddress;
33 import org.onlab.packet.MacAddress; 34 import org.onlab.packet.MacAddress;
34 -import org.onlab.packet.VlanId; 35 +import org.onlab.packet.TCP;
36 +import org.onlab.packet.UDP;
35 import org.onlab.util.ItemNotFoundException; 37 import org.onlab.util.ItemNotFoundException;
36 import org.onlab.util.KryoNamespace; 38 import org.onlab.util.KryoNamespace;
37 import org.onosproject.core.ApplicationId; 39 import org.onosproject.core.ApplicationId;
38 import org.onosproject.core.CoreService; 40 import org.onosproject.core.CoreService;
39 import org.onosproject.net.NshServicePathId; 41 import org.onosproject.net.NshServicePathId;
42 +import org.onosproject.net.PortNumber;
40 import org.onosproject.net.packet.PacketContext; 43 import org.onosproject.net.packet.PacketContext;
41 import org.onosproject.net.packet.PacketProcessor; 44 import org.onosproject.net.packet.PacketProcessor;
42 import org.onosproject.net.packet.PacketService; 45 import org.onosproject.net.packet.PacketService;
...@@ -46,6 +49,9 @@ import org.onosproject.sfc.installer.FlowClassifierInstallerService; ...@@ -46,6 +49,9 @@ import org.onosproject.sfc.installer.FlowClassifierInstallerService;
46 import org.onosproject.sfc.installer.impl.FlowClassifierInstallerImpl; 49 import org.onosproject.sfc.installer.impl.FlowClassifierInstallerImpl;
47 import org.onosproject.sfc.manager.NshSpiIdGenerators; 50 import org.onosproject.sfc.manager.NshSpiIdGenerators;
48 import org.onosproject.sfc.manager.SfcService; 51 import org.onosproject.sfc.manager.SfcService;
52 +import org.onosproject.vtnrsc.DefaultFiveTuple;
53 +import org.onosproject.vtnrsc.FiveTuple;
54 +import org.onosproject.vtnrsc.FixedIp;
49 import org.onosproject.vtnrsc.FlowClassifier; 55 import org.onosproject.vtnrsc.FlowClassifier;
50 import org.onosproject.vtnrsc.FlowClassifierId; 56 import org.onosproject.vtnrsc.FlowClassifierId;
51 import org.onosproject.vtnrsc.PortChain; 57 import org.onosproject.vtnrsc.PortChain;
...@@ -55,10 +61,15 @@ import org.onosproject.vtnrsc.PortPairGroup; ...@@ -55,10 +61,15 @@ import org.onosproject.vtnrsc.PortPairGroup;
55 import org.onosproject.vtnrsc.PortPairGroupId; 61 import org.onosproject.vtnrsc.PortPairGroupId;
56 import org.onosproject.vtnrsc.PortPairId; 62 import org.onosproject.vtnrsc.PortPairId;
57 import org.onosproject.vtnrsc.TenantId; 63 import org.onosproject.vtnrsc.TenantId;
64 +import org.onosproject.vtnrsc.VirtualPort;
65 +import org.onosproject.vtnrsc.VirtualPortId;
58 import org.onosproject.vtnrsc.event.VtnRscEvent; 66 import org.onosproject.vtnrsc.event.VtnRscEvent;
59 import org.onosproject.vtnrsc.event.VtnRscEventFeedback; 67 import org.onosproject.vtnrsc.event.VtnRscEventFeedback;
60 import org.onosproject.vtnrsc.event.VtnRscListener; 68 import org.onosproject.vtnrsc.event.VtnRscListener;
69 +import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
70 +import org.onosproject.vtnrsc.portchain.PortChainService;
61 import org.onosproject.vtnrsc.service.VtnRscService; 71 import org.onosproject.vtnrsc.service.VtnRscService;
72 +import org.onosproject.vtnrsc.virtualport.VirtualPortService;
62 import org.slf4j.Logger; 73 import org.slf4j.Logger;
63 74
64 /** 75 /**
...@@ -71,6 +82,7 @@ public class SfcManager implements SfcService { ...@@ -71,6 +82,7 @@ public class SfcManager implements SfcService {
71 private final Logger log = getLogger(getClass()); 82 private final Logger log = getLogger(getClass());
72 private static final String APP_ID = "org.onosproject.app.vtn"; 83 private static final String APP_ID = "org.onosproject.app.vtn";
73 private static final int SFC_PRIORITY = 1000; 84 private static final int SFC_PRIORITY = 1000;
85 + private static final int NULL_PORT = 0;
74 86
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected VtnRscService vtnRscService; 88 protected VtnRscService vtnRscService;
...@@ -81,6 +93,15 @@ public class SfcManager implements SfcService { ...@@ -81,6 +93,15 @@ public class SfcManager implements SfcService {
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected PacketService packetService; 94 protected PacketService packetService;
83 95
96 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 + protected PortChainService portChainService;
98 +
99 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 + protected FlowClassifierService flowClassifierService;
101 +
102 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 + protected VirtualPortService virtualPortService;
104 +
84 private SfcPacketProcessor processor = new SfcPacketProcessor(); 105 private SfcPacketProcessor processor = new SfcPacketProcessor();
85 106
86 protected ApplicationId appId; 107 protected ApplicationId appId;
...@@ -238,32 +259,193 @@ public class SfcManager implements SfcService { ...@@ -238,32 +259,193 @@ public class SfcManager implements SfcService {
238 259
239 private class SfcPacketProcessor implements PacketProcessor { 260 private class SfcPacketProcessor implements PacketProcessor {
240 261
262 + /**
263 + * Check for given ip match with the fixed ips for the virtual port.
264 + *
265 + * @param vPortId virtual port id
266 + * @param ip ip address to match
267 + * @return true if the ip match with the fixed ips in virtual port false otherwise
268 + */
269 + private boolean checkIpInVirtualPort(VirtualPortId vPortId, IpAddress ip) {
270 + boolean found = false;
271 + Set<FixedIp> ips = virtualPortService.getPort(vPortId).fixedIps();
272 + for (FixedIp fixedIp : ips) {
273 + if (fixedIp.ip().equals(ip)) {
274 + found = true;
275 + break;
276 + }
277 + }
278 + return found;
279 + }
280 +
281 + /**
282 + * Find the port chain for the received packet.
283 + *
284 + * @param fiveTuple five tuple info from the packet
285 + * @return portChainId id of port chain
286 + */
287 + private PortChainId findPortChainFromFiveTuple(FiveTuple fiveTuple) {
288 +
289 + PortChainId portChainId = null;
290 +
291 + Iterable<PortChain> portChains = portChainService.getPortChains();
292 + if (portChains == null) {
293 + log.error("Could not retrive port chain list");
294 + }
295 +
296 + // Identify the port chain to which the packet belongs
297 + for (final PortChain portChain : portChains) {
298 +
299 + Iterable<FlowClassifierId> flowClassifiers = portChain.flowClassifiers();
300 +
301 + // One port chain can have multiple flow classifiers.
302 + for (final FlowClassifierId flowClassifierId : flowClassifiers) {
303 +
304 + FlowClassifier flowClassifier = flowClassifierService.getFlowClassifier(flowClassifierId);
305 + boolean match = false;
306 + // Check whether protocol is set in flow classifier
307 + if (flowClassifier.protocol() != null) {
308 + if ((flowClassifier.protocol().equals("TCP") && fiveTuple.protocol() == IPv4.PROTOCOL_TCP) ||
309 + (flowClassifier.protocol().equals("UDP") &&
310 + fiveTuple.protocol() == IPv4.PROTOCOL_UDP)) {
311 + match = true;
312 + } else {
313 + continue;
314 + }
315 + }
316 +
317 + // Check whether source ip prefix is set in flow classifier
318 + if (flowClassifier.srcIpPrefix() != null) {
319 + if (flowClassifier.srcIpPrefix().contains(fiveTuple.ipSrc())) {
320 + match = true;
321 + } else {
322 + continue;
323 + }
324 + }
325 +
326 + // Check whether destination ip prefix is set in flow classifier
327 + if (flowClassifier.dstIpPrefix() != null) {
328 + if (flowClassifier.dstIpPrefix().contains(fiveTuple.ipDst())) {
329 + match = true;
330 + } else {
331 + continue;
332 + }
333 + }
334 +
335 + // Check whether source port is set in flow classifier
336 + if (fiveTuple.portSrc().toLong() >= flowClassifier.minSrcPortRange() ||
337 + fiveTuple.portSrc().toLong() <= flowClassifier.maxSrcPortRange()) {
338 + match = true;
339 + } else {
340 + continue;
341 + }
342 +
343 + // Check whether destination port is set in flow classifier
344 + if (fiveTuple.portDst().toLong() >= flowClassifier.minSrcPortRange() ||
345 + fiveTuple.portDst().toLong() <= flowClassifier.maxSrcPortRange()) {
346 + match = true;
347 + } else {
348 + continue;
349 + }
350 +
351 + // Check whether neutron source port is set in flow classfier
352 + if ((flowClassifier.srcPort() != null) && (!flowClassifier.srcPort().portId().isEmpty())) {
353 + match = checkIpInVirtualPort(VirtualPortId.portId(flowClassifier.srcPort().portId()),
354 + fiveTuple.ipSrc());
355 + if (!match) {
356 + continue;
357 + }
358 + }
359 +
360 + // Check whether destination neutron destination port is set in flow classifier
361 + if ((flowClassifier.dstPort() != null) && (!flowClassifier.dstPort().portId().isEmpty())) {
362 + match = checkIpInVirtualPort(VirtualPortId.portId(flowClassifier.dstPort().portId()),
363 + fiveTuple.ipDst());
364 + if (!match) {
365 + continue;
366 + }
367 + }
368 +
369 + if (match) {
370 + portChainId = portChain.portChainId();
371 + break;
372 + }
373 + }
374 + }
375 + return portChainId;
376 + }
377 +
378 +
379 + /**
380 + * Get the tenant id for the given mac address.
381 + *
382 + * @param mac mac address
383 + * @return tenantId tenant id for the given mac address
384 + */
385 + private TenantId getTenantId(MacAddress mac) {
386 + Collection<VirtualPort> virtualPorts = virtualPortService.getPorts();
387 + for (VirtualPort virtualPort : virtualPorts) {
388 + if (virtualPort.macAddress().equals(mac)) {
389 + return virtualPort.tenantId();
390 + }
391 + }
392 + return null;
393 + }
394 +
241 @Override 395 @Override
242 public void process(PacketContext context) { 396 public void process(PacketContext context) {
243 Ethernet packet = context.inPacket().parsed(); 397 Ethernet packet = context.inPacket().parsed();
244 if (packet == null) { 398 if (packet == null) {
245 return; 399 return;
246 } 400 }
247 - // get the five tupple parameters for the packet 401 + // get the five tuple parameters for the packet
248 short ethType = packet.getEtherType(); 402 short ethType = packet.getEtherType();
249 - VlanId vlanId = VlanId.vlanId(packet.getVlanID()); 403 + IpAddress ipSrc = null;
250 - MacAddress srcMac = packet.getSourceMAC(); 404 + IpAddress ipDst = null;
251 - MacAddress dstMac = packet.getDestinationMAC(); 405 + int portSrc = 0;
252 - IpAddress ipSrc; 406 + int portDst = 0;
253 - IpAddress ipDst; 407 + byte protocol = 0;
408 + MacAddress macSrc = packet.getSourceMAC();
409 + TenantId tenantId = getTenantId(macSrc);
254 410
255 if (ethType == Ethernet.TYPE_IPV4) { 411 if (ethType == Ethernet.TYPE_IPV4) {
256 IPv4 ipv4Packet = (IPv4) packet.getPayload(); 412 IPv4 ipv4Packet = (IPv4) packet.getPayload();
257 ipSrc = IpAddress.valueOf(ipv4Packet.getSourceAddress()); 413 ipSrc = IpAddress.valueOf(ipv4Packet.getSourceAddress());
258 ipDst = IpAddress.valueOf(ipv4Packet.getDestinationAddress()); 414 ipDst = IpAddress.valueOf(ipv4Packet.getDestinationAddress());
415 + protocol = ipv4Packet.getProtocol();
416 + if (protocol == IPv4.PROTOCOL_TCP) {
417 + TCP tcpPacket = (TCP) ipv4Packet.getPayload();
418 + portSrc = tcpPacket.getSourcePort();
419 + portDst = tcpPacket.getDestinationPort();
420 + } else if (protocol == IPv4.PROTOCOL_UDP) {
421 + UDP udpPacket = (UDP) ipv4Packet.getPayload();
422 + portSrc = udpPacket.getSourcePort();
423 + portDst = udpPacket.getDestinationPort();
424 + }
259 } else if (ethType == Ethernet.TYPE_IPV6) { 425 } else if (ethType == Ethernet.TYPE_IPV6) {
260 - IPv6 ipv6Packet = (IPv6) packet.getPayload(); 426 + return;
261 - ipSrc = IpAddress.valueOf(ipv6Packet.getSourceAddress().toString()); 427 + }
262 - ipDst = IpAddress.valueOf(ipv6Packet.getDestinationAddress().toString()); 428 +
429 +
430 + FiveTuple fiveTuple = DefaultFiveTuple.builder()
431 + .setIpSrc(ipSrc)
432 + .setIpDst(ipDst)
433 + .setPortSrc(PortNumber.portNumber(portSrc))
434 + .setPortDst(PortNumber.portNumber(portDst))
435 + .setProtocol(protocol)
436 + .setTenantId(tenantId)
437 + .build();
438 +
439 + PortChainId portChainId = findPortChainFromFiveTuple(fiveTuple);
440 +
441 + if (portChainId == null) {
442 + log.error("Packet does not match with any classifier");
443 + return;
263 } 444 }
264 445
265 - //todo 446 + // TODO
266 - //identify the port chain to which the packet belongs 447 + // download the required flow rules for classifier and forwarding
448 + // resend the packet back to classifier
267 } 449 }
268 } 450 }
269 } 451 }
......