Konstantinos Kanonakis
Committed by Gerrit Code Review

Reverting to previous iteration mode, fixing case of modifying existing tags and adding extra checks

- Reverting iteration through meta instructions to earlier mode
	Assuming instructions appear in the order they were added
- Saving explicitly provided VlanId to new variable modifiedVlan:
	modifiedVlan is the value to be used when modifying existing tag
	assignedVlan is the value to be pushed to untagged packets
	pushedVlan is the value to be pushed to tagged packets (i.e. when pushVlan == true)
- Extra checks added for the following cases:
	Do not allow to pop tag after modifying existing tag
	Do not allow to modify a tag after pushing a new tag
	Do not allow including multiple modify VLAN operations

Change-Id: I92801e3845a2ca1e88181698cb0ba3c22224acf4
...@@ -58,6 +58,7 @@ import org.onosproject.net.flow.criteria.PortCriterion; ...@@ -58,6 +58,7 @@ import org.onosproject.net.flow.criteria.PortCriterion;
58 import org.onosproject.net.flow.criteria.VlanIdCriterion; 58 import org.onosproject.net.flow.criteria.VlanIdCriterion;
59 import org.onosproject.net.flow.instructions.Instruction; 59 import org.onosproject.net.flow.instructions.Instruction;
60 import org.onosproject.net.flow.instructions.Instructions.OutputInstruction; 60 import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
61 +import org.onosproject.net.flow.instructions.L2ModificationInstruction;
61 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction; 62 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
62 import org.onosproject.net.flowobjective.FilteringObjective; 63 import org.onosproject.net.flowobjective.FilteringObjective;
63 import org.onosproject.net.flowobjective.FlowObjectiveStore; 64 import org.onosproject.net.flowobjective.FlowObjectiveStore;
...@@ -849,7 +850,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -849,7 +850,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
849 850
850 protected List<FlowRule> processVlanIdFilter(VlanIdCriterion vlanIdCriterion, 851 protected List<FlowRule> processVlanIdFilter(VlanIdCriterion vlanIdCriterion,
851 FilteringObjective filt, 852 FilteringObjective filt,
852 - VlanId assignedVlan, 853 + VlanId assignedVlan, VlanId explicitlyAssignedVlan, VlanId pushedVlan,
854 + boolean pushVlan, boolean popVlan,
853 ApplicationId applicationId) { 855 ApplicationId applicationId) {
854 List<FlowRule> rules = new ArrayList<>(); 856 List<FlowRule> rules = new ArrayList<>();
855 log.debug("adding rule for VLAN: {}", vlanIdCriterion.vlanId()); 857 log.debug("adding rule for VLAN: {}", vlanIdCriterion.vlanId());
...@@ -861,6 +863,19 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -861,6 +863,19 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
861 if (vlanIdCriterion.vlanId() != VlanId.NONE) { 863 if (vlanIdCriterion.vlanId() != VlanId.NONE) {
862 selector.matchVlanId(vlanIdCriterion.vlanId()); 864 selector.matchVlanId(vlanIdCriterion.vlanId());
863 selector.matchInPort(p.port()); 865 selector.matchInPort(p.port());
866 + if (popVlan) {
867 + // Pop outer tag
868 + treatment.immediate().popVlan();
869 + }
870 + if (explicitlyAssignedVlan != null && (!popVlan || !vlanIdCriterion.vlanId().equals(assignedVlan))) {
871 + // Modify VLAN ID on single tagged packet or modify remaining tag after popping
872 + // In the first case, do not set VLAN ID again to the already existing value
873 + treatment.immediate().setVlanId(explicitlyAssignedVlan);
874 + }
875 + if (pushVlan) {
876 + // Push new tag
877 + treatment.immediate().pushVlan().setVlanId(pushedVlan);
878 + }
864 } else { 879 } else {
865 selector.matchInPort(p.port()); 880 selector.matchInPort(p.port());
866 treatment.immediate().pushVlan().setVlanId(assignedVlan); 881 treatment.immediate().pushVlan().setVlanId(assignedVlan);
...@@ -910,11 +925,61 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -910,11 +925,61 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
910 } 925 }
911 926
912 VlanId assignedVlan = null; 927 VlanId assignedVlan = null;
928 + VlanId modifiedVlan = null;
929 + VlanId pushedVlan = null;
930 + boolean pushVlan = false;
931 + boolean popVlan = false;
913 if (vlanIdCriterion != null) { 932 if (vlanIdCriterion != null) {
914 - // For VLAN cross-connect packets, use the configured VLAN 933 + if (filt.meta() != null) {
934 + for (Instruction i : filt.meta().allInstructions()) {
935 + if (i instanceof L2ModificationInstruction) {
936 + if (((L2ModificationInstruction) i).subtype()
937 + .equals(L2ModificationInstruction.L2SubType.VLAN_PUSH)) {
938 + pushVlan = true;
939 + } else if (((L2ModificationInstruction) i).subtype()
940 + .equals(L2ModificationInstruction.L2SubType.VLAN_POP)) {
941 + if (modifiedVlan != null) {
942 + log.error("Pop tag is not allowed after modify VLAN operation " +
943 + "in filtering objective", deviceId);
944 + fail(filt, ObjectiveError.BADPARAMS);
945 + return;
946 + }
947 + popVlan = true;
948 + }
949 + }
950 + if (i instanceof ModVlanIdInstruction) {
951 + if (pushVlan && vlanIdCriterion.vlanId() != VlanId.NONE) {
952 + // Modify VLAN should not appear after pushing a new tag
953 + if (pushedVlan != null) {
954 + log.error("Modify VLAN not allowed after push tag operation " +
955 + "in filtering objective", deviceId);
956 + fail(filt, ObjectiveError.BADPARAMS);
957 + return;
958 + }
959 + pushedVlan = ((ModVlanIdInstruction) i).vlanId();
960 + } else if (vlanIdCriterion.vlanId() == VlanId.NONE) {
961 + // For untagged packets the pushed VLAN ID will be saved in assignedVlan
962 + // just to ensure the driver works as designed for the fabric use case
963 + assignedVlan = ((ModVlanIdInstruction) i).vlanId();
964 + } else {
965 + // For tagged packets modifiedVlan will contain the modified value of existing tag
966 + if (modifiedVlan != null) {
967 + log.error("Driver does not allow multiple modify VLAN operations " +
968 + "in the same filtering objective", deviceId);
969 + fail(filt, ObjectiveError.BADPARAMS);
970 + return;
971 + }
972 + modifiedVlan = ((ModVlanIdInstruction) i).vlanId();
973 + }
974 + }
975 + }
976 + }
977 +
978 + // For VLAN cross-connect packets, use the configured VLAN unless there is an explicitly provided VLAN ID
915 if (vlanIdCriterion.vlanId() != VlanId.NONE) { 979 if (vlanIdCriterion.vlanId() != VlanId.NONE) {
980 + if (assignedVlan == null) {
916 assignedVlan = vlanIdCriterion.vlanId(); 981 assignedVlan = vlanIdCriterion.vlanId();
917 - 982 + }
918 // For untagged packets, assign a VLAN ID 983 // For untagged packets, assign a VLAN ID
919 } else { 984 } else {
920 if (filt.meta() == null) { 985 if (filt.meta() == null) {
...@@ -923,11 +988,6 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -923,11 +988,6 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
923 fail(filt, ObjectiveError.BADPARAMS); 988 fail(filt, ObjectiveError.BADPARAMS);
924 return; 989 return;
925 } 990 }
926 - for (Instruction i : filt.meta().allInstructions()) {
927 - if (i instanceof ModVlanIdInstruction) {
928 - assignedVlan = ((ModVlanIdInstruction) i).vlanId();
929 - }
930 - }
931 if (assignedVlan == null) { 991 if (assignedVlan == null) {
932 log.error("Driver requires an assigned vlan-id to tag incoming " 992 log.error("Driver requires an assigned vlan-id to tag incoming "
933 + "untagged packets. Not processing vlan filters on " 993 + "untagged packets. Not processing vlan filters on "
...@@ -936,6 +996,21 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -936,6 +996,21 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
936 return; 996 return;
937 } 997 }
938 } 998 }
999 + if (pushVlan && popVlan) {
1000 + log.error("Cannot push and pop vlan in the same filtering objective");
1001 + fail(filt, ObjectiveError.BADPARAMS);
1002 + return;
1003 + }
1004 + if (popVlan && vlanIdCriterion.vlanId() == VlanId.NONE) {
1005 + log.error("Cannot pop vlan for untagged packets");
1006 + fail(filt, ObjectiveError.BADPARAMS);
1007 + return;
1008 + }
1009 + if ((pushVlan && pushedVlan == null) && vlanIdCriterion.vlanId() != VlanId.NONE) {
1010 + log.error("No VLAN ID provided for push tag operation");
1011 + fail(filt, ObjectiveError.BADPARAMS);
1012 + return;
1013 + }
939 } 1014 }
940 1015
941 if (ethCriterion == null) { 1016 if (ethCriterion == null) {
...@@ -958,7 +1033,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -958,7 +1033,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
958 } else { 1033 } else {
959 for (FlowRule vlanRule : processVlanIdFilter(vlanIdCriterion, 1034 for (FlowRule vlanRule : processVlanIdFilter(vlanIdCriterion,
960 filt, 1035 filt,
961 - assignedVlan, 1036 + assignedVlan, modifiedVlan, pushedVlan,
1037 + pushVlan, popVlan,
962 applicationId)) { 1038 applicationId)) {
963 log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}", 1039 log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}",
964 vlanRule, deviceId); 1040 vlanRule, deviceId);
......
...@@ -205,7 +205,8 @@ public class SpringOpenTTPDell extends SpringOpenTTP { ...@@ -205,7 +205,8 @@ public class SpringOpenTTPDell extends SpringOpenTTP {
205 @Override 205 @Override
206 protected List<FlowRule> processVlanIdFilter(VlanIdCriterion vlanIdCriterion, 206 protected List<FlowRule> processVlanIdFilter(VlanIdCriterion vlanIdCriterion,
207 FilteringObjective filt, 207 FilteringObjective filt,
208 - VlanId assignedVlan, 208 + VlanId assignedVlan, VlanId modifiedVlan, VlanId pushedVlan,
209 + boolean popVlan, boolean pushVlan,
209 ApplicationId applicationId) { 210 ApplicationId applicationId) {
210 log.debug("For now not adding any VLAN rules " 211 log.debug("For now not adding any VLAN rules "
211 + "into Dell switches as it is ignoring"); 212 + "into Dell switches as it is ignoring");
......