Charles Chan
Committed by Gerrit Code Review

CORD-455 Implement multicast support in OFDPA driver

Also refactor Ofdpa2GroupHandler

Change-Id: Id6a9224cab663f57edb8e85a0e7d81e7da3df132
...@@ -26,6 +26,7 @@ import java.util.Set; ...@@ -26,6 +26,7 @@ import java.util.Set;
26 import java.util.concurrent.ConcurrentHashMap; 26 import java.util.concurrent.ConcurrentHashMap;
27 27
28 import com.google.common.collect.ImmutableList; 28 import com.google.common.collect.ImmutableList;
29 +import com.google.common.collect.ImmutableSet;
29 import org.onlab.packet.Ethernet; 30 import org.onlab.packet.Ethernet;
30 import org.onlab.packet.MacAddress; 31 import org.onlab.packet.MacAddress;
31 import org.onlab.packet.IpPrefix; 32 import org.onlab.packet.IpPrefix;
...@@ -99,7 +100,8 @@ public class CpqdOfdpa2Pipeline extends Ofdpa2Pipeline { ...@@ -99,7 +100,8 @@ public class CpqdOfdpa2Pipeline extends Ofdpa2Pipeline {
99 // convert filtering conditions for switch-intfs into flowrules 100 // convert filtering conditions for switch-intfs into flowrules
100 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 101 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
101 for (Criterion criterion : filt.conditions()) { 102 for (Criterion criterion : filt.conditions()) {
102 - if (criterion.type() == Criterion.Type.ETH_DST) { 103 + if (criterion.type() == Criterion.Type.ETH_DST ||
104 + criterion.type() == Criterion.Type.ETH_DST_MASKED) {
103 ethCriterion = (EthCriterion) criterion; 105 ethCriterion = (EthCriterion) criterion;
104 } else if (criterion.type() == Criterion.Type.VLAN_VID) { 106 } else if (criterion.type() == Criterion.Type.VLAN_VID) {
105 vidCriterion = (VlanIdCriterion) criterion; 107 vidCriterion = (VlanIdCriterion) criterion;
...@@ -294,6 +296,11 @@ public class CpqdOfdpa2Pipeline extends Ofdpa2Pipeline { ...@@ -294,6 +296,11 @@ public class CpqdOfdpa2Pipeline extends Ofdpa2Pipeline {
294 return processEthDstOnlyFilter(ethCriterion, applicationId); 296 return processEthDstOnlyFilter(ethCriterion, applicationId);
295 } 297 }
296 298
299 + // Multicast MAC
300 + if (ethCriterion.mask() != null) {
301 + return processMcastEthDstFilter(ethCriterion, applicationId);
302 + }
303 +
297 //handling untagged packets via assigned VLAN 304 //handling untagged packets via assigned VLAN
298 if (vidCriterion.vlanId() == VlanId.NONE) { 305 if (vidCriterion.vlanId() == VlanId.NONE) {
299 vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan); 306 vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
...@@ -416,19 +423,37 @@ public class CpqdOfdpa2Pipeline extends Ofdpa2Pipeline { ...@@ -416,19 +423,37 @@ public class CpqdOfdpa2Pipeline extends Ofdpa2Pipeline {
416 */ 423 */
417 if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) { 424 if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
418 IpPrefix ipv4Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip(); 425 IpPrefix ipv4Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip();
419 - if (ipv4Dst.prefixLength() > 0) { 426 + if (ipv4Dst.isMulticast()) {
420 - filteredSelector.matchEthType(Ethernet.TYPE_IPV4) 427 + if (ipv4Dst.prefixLength() != 32) {
421 - .matchIPDst(ipv4Dst); 428 + log.warn("Multicast specific forwarding objective can only be /32");
429 + fail(fwd, ObjectiveError.BADPARAMS);
430 + return ImmutableSet.of();
431 + }
432 + VlanId assignedVlan = readVlanFromSelector(fwd.meta());
433 + if (assignedVlan == null) {
434 + log.warn("VLAN ID required by multicast specific fwd obj is missing. Abort.");
435 + fail(fwd, ObjectiveError.BADPARAMS);
436 + return ImmutableSet.of();
437 + }
438 + filteredSelector.matchVlanId(assignedVlan);
439 + filteredSelector.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ipv4Dst);
440 + forTableId = MULTICAST_ROUTING_TABLE;
441 + log.debug("processing IPv4 multicast specific forwarding objective {} -> next:{}"
442 + + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
422 } else { 443 } else {
423 - filteredSelector.matchEthType(Ethernet.TYPE_IPV4) 444 + if (ipv4Dst.prefixLength() > 0) {
424 - .matchIPDst(IpPrefix.valueOf("0.0.0.0/1")); 445 + filteredSelector.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ipv4Dst);
425 - complementarySelector.matchEthType(Ethernet.TYPE_IPV4) 446 + } else {
426 - .matchIPDst(IpPrefix.valueOf("128.0.0.0/1")); 447 + filteredSelector.matchEthType(Ethernet.TYPE_IPV4)
427 - defaultRule = true; 448 + .matchIPDst(IpPrefix.valueOf("0.0.0.0/1"));
449 + complementarySelector.matchEthType(Ethernet.TYPE_IPV4)
450 + .matchIPDst(IpPrefix.valueOf("128.0.0.0/1"));
451 + defaultRule = true;
452 + }
453 + forTableId = UNICAST_ROUTING_TABLE;
454 + log.debug("processing IPv4 unicast specific forwarding objective {} -> next:{}"
455 + + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
428 } 456 }
429 - forTableId = UNICAST_ROUTING_TABLE;
430 - log.debug("processing IPv4 specific forwarding objective {} -> next:{}"
431 - + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
432 } else { 457 } else {
433 filteredSelector 458 filteredSelector
434 .matchEthType(Ethernet.MPLS_UNICAST) 459 .matchEthType(Ethernet.MPLS_UNICAST)
......
...@@ -83,6 +83,11 @@ public class CpqdOfdpa2VlanPipeline extends CpqdOfdpa2Pipeline { ...@@ -83,6 +83,11 @@ public class CpqdOfdpa2VlanPipeline extends CpqdOfdpa2Pipeline {
83 return processEthDstOnlyFilter(ethCriterion, applicationId); 83 return processEthDstOnlyFilter(ethCriterion, applicationId);
84 } 84 }
85 85
86 + // Multicast MAC
87 + if (ethCriterion.mask() != null) {
88 + return processMcastEthDstFilter(ethCriterion, applicationId);
89 + }
90 +
86 //handling untagged packets via assigned VLAN 91 //handling untagged packets via assigned VLAN
87 if (vidCriterion.vlanId() == VlanId.NONE) { 92 if (vidCriterion.vlanId() == VlanId.NONE) {
88 vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan); 93 vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
......
...@@ -28,6 +28,7 @@ import java.util.Set; ...@@ -28,6 +28,7 @@ import java.util.Set;
28 import java.util.concurrent.ConcurrentHashMap; 28 import java.util.concurrent.ConcurrentHashMap;
29 29
30 import com.google.common.collect.ImmutableList; 30 import com.google.common.collect.ImmutableList;
31 +import com.google.common.collect.ImmutableSet;
31 import org.onlab.osgi.ServiceDirectory; 32 import org.onlab.osgi.ServiceDirectory;
32 import org.onlab.packet.Ethernet; 33 import org.onlab.packet.Ethernet;
33 import org.onlab.packet.IpPrefix; 34 import org.onlab.packet.IpPrefix;
...@@ -297,7 +298,8 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -297,7 +298,8 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
297 // convert filtering conditions for switch-intfs into flowrules 298 // convert filtering conditions for switch-intfs into flowrules
298 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 299 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
299 for (Criterion criterion : filt.conditions()) { 300 for (Criterion criterion : filt.conditions()) {
300 - if (criterion.type() == Criterion.Type.ETH_DST) { 301 + if (criterion.type() == Criterion.Type.ETH_DST ||
302 + criterion.type() == Criterion.Type.ETH_DST_MASKED) {
301 ethCriterion = (EthCriterion) criterion; 303 ethCriterion = (EthCriterion) criterion;
302 } else if (criterion.type() == Criterion.Type.VLAN_VID) { 304 } else if (criterion.type() == Criterion.Type.VLAN_VID) {
303 vidCriterion = (VlanIdCriterion) criterion; 305 vidCriterion = (VlanIdCriterion) criterion;
...@@ -559,6 +561,11 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -559,6 +561,11 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
559 return processEthDstOnlyFilter(ethCriterion, applicationId); 561 return processEthDstOnlyFilter(ethCriterion, applicationId);
560 } 562 }
561 563
564 + // Multicast MAC
565 + if (ethCriterion.mask() != null) {
566 + return processMcastEthDstFilter(ethCriterion, applicationId);
567 + }
568 +
562 //handling untagged packets via assigned VLAN 569 //handling untagged packets via assigned VLAN
563 if (vidCriterion.vlanId() == VlanId.NONE) { 570 if (vidCriterion.vlanId() == VlanId.NONE) {
564 vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan); 571 vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
...@@ -635,6 +642,24 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -635,6 +642,24 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
635 return ImmutableList.<FlowRule>builder().add(rule).build(); 642 return ImmutableList.<FlowRule>builder().add(rule).build();
636 } 643 }
637 644
645 + protected List<FlowRule> processMcastEthDstFilter(EthCriterion ethCriterion,
646 + ApplicationId applicationId) {
647 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
648 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
649 + selector.matchEthType(Ethernet.TYPE_IPV4);
650 + selector.matchEthDstMasked(ethCriterion.mac(), ethCriterion.mask());
651 + treatment.transition(MULTICAST_ROUTING_TABLE);
652 + FlowRule rule = DefaultFlowRule.builder()
653 + .forDevice(deviceId)
654 + .withSelector(selector.build())
655 + .withTreatment(treatment.build())
656 + .withPriority(DEFAULT_PRIORITY)
657 + .fromApp(applicationId)
658 + .makePermanent()
659 + .forTable(TMAC_TABLE).build();
660 + return ImmutableList.<FlowRule>builder().add(rule).build();
661 + }
662 +
638 private Collection<FlowRule> processForward(ForwardingObjective fwd) { 663 private Collection<FlowRule> processForward(ForwardingObjective fwd) {
639 switch (fwd.flag()) { 664 switch (fwd.flag()) {
640 case SPECIFIC: 665 case SPECIFIC:
...@@ -802,19 +827,38 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -802,19 +827,38 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
802 */ 827 */
803 if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) { 828 if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
804 IpPrefix ipv4Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip(); 829 IpPrefix ipv4Dst = ((IPCriterion) selector.getCriterion(Criterion.Type.IPV4_DST)).ip();
805 - if (ipv4Dst.prefixLength() > 0) { 830 + if (ipv4Dst.isMulticast()) {
806 - filteredSelector.matchEthType(Ethernet.TYPE_IPV4) 831 + if (ipv4Dst.prefixLength() != 32) {
807 - .matchIPDst(ipv4Dst); 832 + log.warn("Multicast specific forwarding objective can only be /32");
833 + fail(fwd, ObjectiveError.BADPARAMS);
834 + return ImmutableSet.of();
835 + }
836 + VlanId assignedVlan = readVlanFromSelector(fwd.meta());
837 + if (assignedVlan == null) {
838 + log.warn("VLAN ID required by multicast specific fwd obj is missing. Abort.");
839 + fail(fwd, ObjectiveError.BADPARAMS);
840 + return ImmutableSet.of();
841 + }
842 + OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(assignedVlan);
843 + filteredSelector.extension(ofdpaMatchVlanVid, deviceId);
844 + filteredSelector.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ipv4Dst);
845 + forTableId = MULTICAST_ROUTING_TABLE;
846 + log.debug("processing IPv4 multicast specific forwarding objective {} -> next:{}"
847 + + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
808 } else { 848 } else {
809 - filteredSelector.matchEthType(Ethernet.TYPE_IPV4) 849 + if (ipv4Dst.prefixLength() > 0) {
810 - .matchIPDst(IpPrefix.valueOf("0.0.0.0/1")); 850 + filteredSelector.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ipv4Dst);
811 - complementarySelector.matchEthType(Ethernet.TYPE_IPV4) 851 + } else {
812 - .matchIPDst(IpPrefix.valueOf("128.0.0.0/1")); 852 + filteredSelector.matchEthType(Ethernet.TYPE_IPV4)
813 - defaultRule = true; 853 + .matchIPDst(IpPrefix.valueOf("0.0.0.0/1"));
854 + complementarySelector.matchEthType(Ethernet.TYPE_IPV4)
855 + .matchIPDst(IpPrefix.valueOf("128.0.0.0/1"));
856 + defaultRule = true;
857 + }
858 + forTableId = UNICAST_ROUTING_TABLE;
859 + log.debug("processing IPv4 unicast specific forwarding objective {} -> next:{}"
860 + + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
814 } 861 }
815 - forTableId = UNICAST_ROUTING_TABLE;
816 - log.debug("processing IPv4 specific forwarding objective {} -> next:{}"
817 - + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
818 862
819 if (fwd.treatment() != null) { 863 if (fwd.treatment() != null) {
820 for (Instruction instr : fwd.treatment().allInstructions()) { 864 for (Instruction instr : fwd.treatment().allInstructions()) {
...@@ -1057,4 +1101,15 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -1057,4 +1101,15 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline
1057 } 1101 }
1058 return mappings; 1102 return mappings;
1059 } 1103 }
1104 +
1105 + protected static VlanId readVlanFromSelector(TrafficSelector selector) {
1106 + Criterion criterion = selector.getCriterion(Criterion.Type.VLAN_VID);
1107 + return (criterion == null)
1108 + ? null : ((VlanIdCriterion) criterion).vlanId();
1109 + }
1110 +
1111 + protected static IpPrefix readIpDstFromSelector(TrafficSelector selector) {
1112 + Criterion criterion = selector.getCriterion(Criterion.Type.IPV4_DST);
1113 + return (criterion == null) ? null : ((IPCriterion) criterion).ip();
1114 + }
1060 } 1115 }
......