Charles Chan
Committed by Yuta HIGUCHI

CORD-389 Fix for Accton 6712 deployment

Related to this topic:
- Disable the meter collector since right now it is not supported
- Implement extension VLAN ID selector/treatment for OFDPA
    Since it requires two special flow entries to match untagged packets
        0x1ffe/no mask (filtering rule, need to go first)
        0x0000/0x1fff setvid 0x0ffe (assignment rule, need to go second)
- Not able to point /32 IP address to ECMP group. Use /31 instead.

In addition:
- Implement serializer for ExtensionCriterion

Change-Id: I621b3ad14014d7e6945c014cdae4f7cd2939288e
Showing 19 changed files with 697 additions and 75 deletions
...@@ -230,6 +230,13 @@ public class RoutingRulePopulator { ...@@ -230,6 +230,13 @@ public class RoutingRulePopulator {
230 public boolean populateIpRuleForRouter(DeviceId deviceId, 230 public boolean populateIpRuleForRouter(DeviceId deviceId,
231 IpPrefix ipPrefix, DeviceId destSw, 231 IpPrefix ipPrefix, DeviceId destSw,
232 Set<DeviceId> nextHops) { 232 Set<DeviceId> nextHops) {
233 + // TODO: OFDPA does not support /32 with ECMP group at this moment.
234 + // Use /31 instead
235 + IpPrefix effectivePrefix =
236 + (ipPrefix.prefixLength() == IpPrefix.MAX_INET_MASK_LENGTH) ?
237 + IpPrefix.valueOf(ipPrefix.getIp4Prefix().address(), 31) :
238 + ipPrefix;
239 +
233 int segmentId; 240 int segmentId;
234 try { 241 try {
235 segmentId = config.getSegmentId(destSw); 242 segmentId = config.getSegmentId(destSw);
...@@ -239,7 +246,7 @@ public class RoutingRulePopulator { ...@@ -239,7 +246,7 @@ public class RoutingRulePopulator {
239 } 246 }
240 247
241 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder(); 248 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
242 - sbuilder.matchIPDst(ipPrefix); 249 + sbuilder.matchIPDst(effectivePrefix);
243 sbuilder.matchEthType(Ethernet.TYPE_IPV4); 250 sbuilder.matchEthType(Ethernet.TYPE_IPV4);
244 TrafficSelector selector = sbuilder.build(); 251 TrafficSelector selector = sbuilder.build();
245 252
...@@ -277,7 +284,7 @@ public class RoutingRulePopulator { ...@@ -277,7 +284,7 @@ public class RoutingRulePopulator {
277 .makePermanent() 284 .makePermanent()
278 .nextStep(nextId) 285 .nextStep(nextId)
279 .withSelector(selector) 286 .withSelector(selector)
280 - .withPriority(2000 * ipPrefix.prefixLength()) 287 + .withPriority(2000 * effectivePrefix.prefixLength())
281 .withFlag(ForwardingObjective.Flag.SPECIFIC); 288 .withFlag(ForwardingObjective.Flag.SPECIFIC);
282 if (treatment != null) { 289 if (treatment != null) {
283 fwdBuilder.withTreatment(treatment); 290 fwdBuilder.withTreatment(treatment);
......
...@@ -615,9 +615,9 @@ public final class Criteria { ...@@ -615,9 +615,9 @@ public final class Criteria {
615 * 615 *
616 * @param extensionSelector extension selector 616 * @param extensionSelector extension selector
617 * @param deviceId device ID 617 * @param deviceId device ID
618 - * @return match criterion 618 + * @return match extension criterion
619 */ 619 */
620 - public static Criterion extension(ExtensionSelector extensionSelector, 620 + public static ExtensionCriterion extension(ExtensionSelector extensionSelector,
621 DeviceId deviceId) { 621 DeviceId deviceId) {
622 return new ExtensionCriterion(extensionSelector, deviceId); 622 return new ExtensionCriterion(extensionSelector, deviceId);
623 } 623 }
......
...@@ -37,8 +37,8 @@ public class ExtensionSelectorType { ...@@ -37,8 +37,8 @@ public class ExtensionSelectorType {
37 NICIRA_MATCH_NSH_CH1(2), 37 NICIRA_MATCH_NSH_CH1(2),
38 NICIRA_MATCH_NSH_CH2(3), 38 NICIRA_MATCH_NSH_CH2(3),
39 NICIRA_MATCH_NSH_CH3(4), 39 NICIRA_MATCH_NSH_CH3(4),
40 - NICIRA_MATCH_NSH_CH4(5); 40 + NICIRA_MATCH_NSH_CH4(5),
41 - 41 + OFDPA_MATCH_VLAN_VID(16);
42 42
43 private ExtensionSelectorType type; 43 private ExtensionSelectorType type;
44 44
......
...@@ -34,6 +34,10 @@ public final class ExtensionTreatmentType { ...@@ -34,6 +34,10 @@ public final class ExtensionTreatmentType {
34 public enum ExtensionTreatmentTypes { 34 public enum ExtensionTreatmentTypes {
35 NICIRA_SET_TUNNEL_DST(0), 35 NICIRA_SET_TUNNEL_DST(0),
36 NICIRA_RESUBMIT(1), 36 NICIRA_RESUBMIT(1),
37 + NICIRA_MOV_ARP_SHA_TO_THA(2),
38 + NICIRA_MOV_ARP_SPA_TO_TPA(3),
39 + NICIRA_MOV_ETH_SRC_TO_DST(4),
40 + NICIRA_MOV_IP_SRC_TO_DST(5),
37 NICIRA_RESUBMIT_TABLE(14), 41 NICIRA_RESUBMIT_TABLE(14),
38 NICIRA_SET_NSH_SPI(32), 42 NICIRA_SET_NSH_SPI(32),
39 NICIRA_SET_NSH_SI(33), 43 NICIRA_SET_NSH_SI(33),
...@@ -41,10 +45,7 @@ public final class ExtensionTreatmentType { ...@@ -41,10 +45,7 @@ public final class ExtensionTreatmentType {
41 NICIRA_SET_NSH_CH2(35), 45 NICIRA_SET_NSH_CH2(35),
42 NICIRA_SET_NSH_CH3(36), 46 NICIRA_SET_NSH_CH3(36),
43 NICIRA_SET_NSH_CH4(37), 47 NICIRA_SET_NSH_CH4(37),
44 - NICIRA_MOV_ARP_SHA_TO_THA(2), 48 + OFDPA_SET_VLAN_ID(64);
45 - NICIRA_MOV_ARP_SPA_TO_TPA(3),
46 - NICIRA_MOV_ETH_SRC_TO_DST(4),
47 - NICIRA_MOV_IP_SRC_TO_DST(5);
48 49
49 private ExtensionTreatmentType type; 50 private ExtensionTreatmentType type;
50 51
......
1 +/*
2 + * Copyright 2015-2016 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 +
17 +package org.onosproject.store.serializers;
18 +
19 +import com.esotericsoftware.kryo.Kryo;
20 +import com.esotericsoftware.kryo.Serializer;
21 +import com.esotericsoftware.kryo.io.Input;
22 +import com.esotericsoftware.kryo.io.Output;
23 +import org.onlab.osgi.DefaultServiceDirectory;
24 +import org.onosproject.net.DeviceId;
25 +import org.onosproject.net.behaviour.ExtensionSelectorResolver;
26 +import org.onosproject.net.driver.DefaultDriverData;
27 +import org.onosproject.net.driver.DefaultDriverHandler;
28 +import org.onosproject.net.driver.DriverHandler;
29 +import org.onosproject.net.driver.DriverService;
30 +import org.onosproject.net.flow.criteria.Criteria;
31 +import org.onosproject.net.flow.criteria.ExtensionCriterion;
32 +import org.onosproject.net.flow.criteria.ExtensionSelector;
33 +import org.onosproject.net.flow.criteria.ExtensionSelectorType;
34 +
35 +/**
36 + * Serializer for extension criteria.
37 + */
38 +public class ExtensionCriterionSerializer extends Serializer<ExtensionCriterion> {
39 +
40 + /**
41 + * Constructs a extension criterion serializer.
42 + */
43 + public ExtensionCriterionSerializer() {
44 + super(false, true);
45 + }
46 +
47 + @Override
48 + public void write(Kryo kryo, Output output, ExtensionCriterion object) {
49 + kryo.writeClassAndObject(output, object.extensionSelector().type());
50 + kryo.writeClassAndObject(output, object.deviceId());
51 + kryo.writeClassAndObject(output, object.extensionSelector().serialize());
52 + }
53 +
54 + @Override
55 + public ExtensionCriterion read(Kryo kryo, Input input,
56 + Class<ExtensionCriterion> type) {
57 + ExtensionSelectorType exType = (ExtensionSelectorType) kryo.readClassAndObject(input);
58 + DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input);
59 +
60 + DriverService driverService = DefaultServiceDirectory.getService(DriverService.class);
61 + DriverHandler handler = new DefaultDriverHandler(
62 + new DefaultDriverData(driverService.getDriver(deviceId), deviceId));
63 +
64 + ExtensionSelectorResolver resolver = handler.behaviour(ExtensionSelectorResolver.class);
65 + ExtensionSelector selector = resolver.getExtensionSelector(exType);
66 +
67 + byte[] bytes = (byte[]) kryo.readClassAndObject(input);
68 + selector.deserialize(bytes);
69 + return Criteria.extension(selector, deviceId);
70 + }
71 +}
1 /* 1 /*
2 - * Copyright 2015 Open Networking Laboratory 2 + * Copyright 2015-2016 Open Networking Laboratory
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
...@@ -32,11 +32,14 @@ import org.onosproject.net.flow.instructions.ExtensionTreatmentType; ...@@ -32,11 +32,14 @@ import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
32 import org.onosproject.net.flow.instructions.Instructions; 32 import org.onosproject.net.flow.instructions.Instructions;
33 33
34 /** 34 /**
35 - * Created by jono on 10/29/15. 35 + * Serializer for extension instructions.
36 */ 36 */
37 public class ExtensionInstructionSerializer extends 37 public class ExtensionInstructionSerializer extends
38 Serializer<Instructions.ExtensionInstructionWrapper> { 38 Serializer<Instructions.ExtensionInstructionWrapper> {
39 39
40 + /**
41 + * Constructs a extension instruction serializer.
42 + */
40 public ExtensionInstructionSerializer() { 43 public ExtensionInstructionSerializer() {
41 super(false, true); 44 super(false, true);
42 } 45 }
...@@ -45,9 +48,7 @@ public class ExtensionInstructionSerializer extends ...@@ -45,9 +48,7 @@ public class ExtensionInstructionSerializer extends
45 public void write(Kryo kryo, Output output, Instructions.ExtensionInstructionWrapper object) { 48 public void write(Kryo kryo, Output output, Instructions.ExtensionInstructionWrapper object) {
46 kryo.writeClassAndObject(output, object.extensionInstruction().type()); 49 kryo.writeClassAndObject(output, object.extensionInstruction().type());
47 kryo.writeClassAndObject(output, object.deviceId()); 50 kryo.writeClassAndObject(output, object.deviceId());
48 -
49 kryo.writeClassAndObject(output, object.extensionInstruction().serialize()); 51 kryo.writeClassAndObject(output, object.extensionInstruction().serialize());
50 -
51 } 52 }
52 53
53 @Override 54 @Override
...@@ -61,7 +62,6 @@ public class ExtensionInstructionSerializer extends ...@@ -61,7 +62,6 @@ public class ExtensionInstructionSerializer extends
61 new DefaultDriverData(driverService.getDriver(deviceId), deviceId)); 62 new DefaultDriverData(driverService.getDriver(deviceId), deviceId));
62 63
63 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class); 64 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
64 -
65 ExtensionTreatment instruction = resolver.getExtensionInstruction(exType); 65 ExtensionTreatment instruction = resolver.getExtensionInstruction(exType);
66 66
67 byte[] bytes = (byte[]) kryo.readClassAndObject(input); 67 byte[] bytes = (byte[]) kryo.readClassAndObject(input);
......
...@@ -108,6 +108,8 @@ import org.onosproject.net.flow.criteria.ArpPaCriterion; ...@@ -108,6 +108,8 @@ import org.onosproject.net.flow.criteria.ArpPaCriterion;
108 import org.onosproject.net.flow.criteria.Criterion; 108 import org.onosproject.net.flow.criteria.Criterion;
109 import org.onosproject.net.flow.criteria.EthCriterion; 109 import org.onosproject.net.flow.criteria.EthCriterion;
110 import org.onosproject.net.flow.criteria.EthTypeCriterion; 110 import org.onosproject.net.flow.criteria.EthTypeCriterion;
111 +import org.onosproject.net.flow.criteria.ExtensionCriterion;
112 +import org.onosproject.net.flow.criteria.ExtensionSelectorType;
111 import org.onosproject.net.flow.criteria.IPCriterion; 113 import org.onosproject.net.flow.criteria.IPCriterion;
112 import org.onosproject.net.flow.criteria.IPDscpCriterion; 114 import org.onosproject.net.flow.criteria.IPDscpCriterion;
113 import org.onosproject.net.flow.criteria.IPEcnCriterion; 115 import org.onosproject.net.flow.criteria.IPEcnCriterion;
...@@ -482,6 +484,8 @@ public final class KryoNamespaces { ...@@ -482,6 +484,8 @@ public final class KryoNamespaces {
482 .register(new DefaultOutboundPacketSerializer(), DefaultOutboundPacket.class) 484 .register(new DefaultOutboundPacketSerializer(), DefaultOutboundPacket.class)
483 .register(new AnnotationsSerializer(), DefaultAnnotations.class) 485 .register(new AnnotationsSerializer(), DefaultAnnotations.class)
484 .register(new ExtensionInstructionSerializer(), Instructions.ExtensionInstructionWrapper.class) 486 .register(new ExtensionInstructionSerializer(), Instructions.ExtensionInstructionWrapper.class)
487 + .register(new ExtensionCriterionSerializer(), ExtensionCriterion.class)
488 + .register(ExtensionSelectorType.class)
485 .register(ExtensionTreatmentType.class) 489 .register(ExtensionTreatmentType.class)
486 .register(Versioned.class) 490 .register(Versioned.class)
487 .register(MapEvent.class) 491 .register(MapEvent.class)
......
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.driver.extensions;
18 +
19 +import org.onlab.packet.VlanId;
20 +import org.onosproject.net.behaviour.ExtensionSelectorResolver;
21 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
22 +import org.onosproject.net.flow.criteria.ExtensionSelector;
23 +import org.onosproject.net.flow.criteria.ExtensionSelectorType;
24 +import org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes;
25 +import org.onosproject.openflow.controller.ExtensionSelectorInterpreter;
26 +import org.projectfloodlight.openflow.protocol.OFFactory;
27 +import org.projectfloodlight.openflow.protocol.match.MatchField;
28 +import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
29 +import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
30 +import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVidMasked;
31 +import org.projectfloodlight.openflow.types.OFVlanVidMatch;
32 +import org.projectfloodlight.openflow.types.VlanVid;
33 +
34 +/**
35 + * Interpreter for OFDPA OpenFlow selector extensions.
36 + */
37 +public class OfdpaExtensionSelectorInterpreter extends AbstractHandlerBehaviour
38 + implements ExtensionSelectorInterpreter, ExtensionSelectorResolver {
39 +
40 + @Override
41 + public boolean supported(ExtensionSelectorType extensionSelectorType) {
42 + if (extensionSelectorType.equals(ExtensionSelectorTypes.OFDPA_MATCH_VLAN_VID.type())) {
43 + return true;
44 + }
45 + return false;
46 + }
47 +
48 + @Override
49 + public OFOxm<?> mapSelector(OFFactory factory, ExtensionSelector extensionSelector) {
50 + ExtensionSelectorType type = extensionSelector.type();
51 + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.OFDPA_MATCH_VLAN_VID.type())) {
52 + VlanId vlanId = ((OfdpaMatchVlanVid) extensionSelector).vlanId();
53 + // Special VLAN 0x0000/0x1FFF required by OFDPA
54 + if (vlanId.toShort() == 0x0000) {
55 + OFVlanVidMatch vid = OFVlanVidMatch.ofRawVid(vlanId.toShort());
56 + OFVlanVidMatch mask = OFVlanVidMatch.ofRawVid((short) 0x1FFF);
57 + return factory.oxms().vlanVidMasked(vid, mask);
58 + // Normal case
59 + } else if (vlanId.equals(VlanId.ANY)) {
60 + return factory.oxms().vlanVidMasked(OFVlanVidMatch.PRESENT, OFVlanVidMatch.PRESENT);
61 + } else if (vlanId.equals(VlanId.NONE)) {
62 + return factory.oxms().vlanVid(OFVlanVidMatch.NONE);
63 + } else {
64 + return factory.oxms().vlanVid(OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vlanId.toShort())));
65 + }
66 + }
67 + throw new UnsupportedOperationException(
68 + "Unexpected ExtensionSelector: " + extensionSelector.toString());
69 + }
70 +
71 + @Override
72 + public ExtensionSelector mapOxm(OFOxm<?> oxm) {
73 + VlanId vlanId;
74 +
75 + if (oxm.getMatchField().equals(MatchField.VLAN_VID)) {
76 + if (oxm.isMasked()) {
77 + OFVlanVidMatch vid = ((OFOxmVlanVidMasked) oxm).getValue();
78 + OFVlanVidMatch mask = ((OFOxmVlanVidMasked) oxm).getMask();
79 +
80 + if (vid.equals(OFVlanVidMatch.ofRawVid((short) 0))) {
81 + vlanId = VlanId.vlanId((short) 0);
82 + } else if (vid.equals(OFVlanVidMatch.PRESENT) &&
83 + mask.equals(OFVlanVidMatch.PRESENT)) {
84 + vlanId = VlanId.ANY;
85 + } else {
86 + vlanId = VlanId.vlanId(vid.getVlan());
87 + }
88 + } else {
89 + OFVlanVidMatch vid = ((OFOxmVlanVid) oxm).getValue();
90 +
91 + if (!vid.isPresentBitSet()) {
92 + vlanId = VlanId.NONE;
93 + } else {
94 + vlanId = VlanId.vlanId(vid.getVlan());
95 + }
96 + }
97 + return new OfdpaMatchVlanVid(vlanId);
98 + }
99 + throw new UnsupportedOperationException(
100 + "Unexpected OXM: " + oxm.toString());
101 + }
102 +
103 + @Override
104 + public ExtensionSelector getExtensionSelector(ExtensionSelectorType type) {
105 + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.OFDPA_MATCH_VLAN_VID.type())) {
106 + return new OfdpaMatchVlanVid();
107 + }
108 + throw new UnsupportedOperationException(
109 + "Driver does not support extension type " + type.toString());
110 + }
111 +}
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.driver.extensions;
18 +
19 +import org.onlab.packet.VlanId;
20 +import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
21 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
22 +import org.onosproject.net.flow.instructions.ExtensionTreatment;
23 +import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
24 +import org.onosproject.openflow.controller.ExtensionTreatmentInterpreter;
25 +import org.projectfloodlight.openflow.protocol.OFActionType;
26 +import org.projectfloodlight.openflow.protocol.OFFactory;
27 +import org.projectfloodlight.openflow.protocol.action.OFAction;
28 +import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
29 +import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
30 +import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid;
31 +import org.projectfloodlight.openflow.types.OFVlanVidMatch;
32 +
33 +/**
34 + * Interpreter for OFDPA OpenFlow treatment extensions.
35 + */
36 +public class OfdpaExtensionTreatmentInterpreter extends AbstractHandlerBehaviour
37 + implements ExtensionTreatmentInterpreter, ExtensionTreatmentResolver {
38 + @Override
39 + public boolean supported(ExtensionTreatmentType extensionTreatmentType) {
40 + if (extensionTreatmentType.equals(
41 + ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_VLAN_ID.type())) {
42 + return true;
43 + }
44 + return false;
45 + }
46 +
47 + @Override
48 + public OFAction mapInstruction(OFFactory factory, ExtensionTreatment extensionTreatment) {
49 + ExtensionTreatmentType type = extensionTreatment.type();
50 + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_VLAN_ID.type())) {
51 + VlanId vlanId = ((OfdpaSetVlanVid) extensionTreatment).vlanId();
52 + // NOTE: OFDPA requires isPresent bit set to zero.
53 + OFVlanVidMatch match = OFVlanVidMatch.ofRawVid(vlanId.toShort());
54 + return factory.actions().setField(factory.oxms().vlanVid(match));
55 + }
56 + throw new UnsupportedOperationException(
57 + "Unexpected ExtensionTreatment: " + extensionTreatment.toString());
58 + }
59 +
60 + @Override
61 + public ExtensionTreatment mapAction(OFAction action) {
62 + if (action.getType().equals(OFActionType.SET_FIELD)) {
63 + OFActionSetField setFieldAction = (OFActionSetField) action;
64 + OFOxm<?> oxm = setFieldAction.getField();
65 + switch (oxm.getMatchField().id) {
66 + case VLAN_VID:
67 + OFOxmVlanVid vlanVid = (OFOxmVlanVid) oxm;
68 + return new OfdpaSetVlanVid(VlanId.vlanId(vlanVid.getValue().getRawVid()));
69 + default:
70 + throw new UnsupportedOperationException(
71 + "Driver does not support extension type " + oxm.getMatchField().id);
72 + }
73 + }
74 + throw new UnsupportedOperationException(
75 + "Unexpected OFAction: " + action.toString());
76 + }
77 +
78 + @Override
79 + public ExtensionTreatment getExtensionInstruction(ExtensionTreatmentType type) {
80 + if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_VLAN_ID.type())) {
81 + return new OfdpaSetVlanVid();
82 + }
83 + throw new UnsupportedOperationException(
84 + "Driver does not support extension type " + type.toString());
85 + }
86 +}
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.driver.extensions;
18 +
19 +import com.google.common.base.MoreObjects;
20 +import org.onlab.packet.VlanId;
21 +import org.onlab.util.KryoNamespace;
22 +import org.onosproject.net.flow.AbstractExtension;
23 +import org.onosproject.net.flow.criteria.ExtensionSelector;
24 +import org.onosproject.net.flow.criteria.ExtensionSelectorType;
25 +
26 +import java.util.Objects;
27 +
28 +import static com.google.common.base.Preconditions.checkNotNull;
29 +
30 +/**
31 + * OFDPA VLAN ID extension match.
32 + */
33 +public class OfdpaMatchVlanVid extends AbstractExtension implements ExtensionSelector {
34 + private VlanId vlanId;
35 +
36 + private static final KryoNamespace APPKRYO = new KryoNamespace.Builder()
37 + .register(VlanId.class)
38 + .build();
39 +
40 + /**
41 + * OFDPA VLAN ID extension match.
42 + */
43 + protected OfdpaMatchVlanVid() {
44 + vlanId = null;
45 + }
46 +
47 + /**
48 + * Constructs a new VLAN ID match with given VLAN ID.
49 + *
50 + * @param vlanId VLAN ID
51 + */
52 + public OfdpaMatchVlanVid(VlanId vlanId) {
53 + checkNotNull(vlanId);
54 + this.vlanId = vlanId;
55 + }
56 +
57 + /**
58 + * Gets the VLAN ID.
59 + *
60 + * @return VLAN ID
61 + */
62 + public VlanId vlanId() {
63 + return vlanId;
64 + }
65 +
66 + @Override
67 + public ExtensionSelectorType type() {
68 + return ExtensionSelectorType.ExtensionSelectorTypes.OFDPA_MATCH_VLAN_VID.type();
69 + }
70 +
71 + @Override
72 + public void deserialize(byte[] data) {
73 + vlanId = APPKRYO.deserialize(data);
74 + }
75 +
76 + @Override
77 + public byte[] serialize() {
78 + return APPKRYO.serialize(vlanId);
79 + }
80 +
81 + @Override
82 + public int hashCode() {
83 + return Objects.hash(vlanId);
84 + }
85 +
86 + @Override
87 + public boolean equals(Object obj) {
88 + if (this == obj) {
89 + return true;
90 + }
91 + if (obj instanceof OfdpaMatchVlanVid) {
92 + OfdpaMatchVlanVid that = (OfdpaMatchVlanVid) obj;
93 + return Objects.equals(vlanId, that.vlanId);
94 +
95 + }
96 + return false;
97 + }
98 +
99 + @Override
100 + public String toString() {
101 + return MoreObjects.toStringHelper(getClass())
102 + .add("vlanId", vlanId)
103 + .toString();
104 + }
105 +}
1 +/*
2 + * Copyright 2016 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 +
17 +package org.onosproject.driver.extensions;
18 +
19 +import com.google.common.base.MoreObjects;
20 +import org.onlab.packet.VlanId;
21 +import org.onlab.util.KryoNamespace;
22 +import org.onosproject.net.flow.AbstractExtension;
23 +import org.onosproject.net.flow.instructions.ExtensionTreatment;
24 +import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
25 +
26 +import java.util.Objects;
27 +
28 +import static com.google.common.base.Preconditions.checkNotNull;
29 +
30 +/**
31 + * OFDPA set VLAN ID extension instruction.
32 + */
33 +public class OfdpaSetVlanVid extends AbstractExtension implements ExtensionTreatment {
34 + private VlanId vlanId;
35 +
36 + private static final KryoNamespace APPKRYO = new KryoNamespace.Builder()
37 + .register(VlanId.class)
38 + .build();
39 +
40 + /**
41 + * Constructs a new set VLAN ID instruction.
42 + */
43 + protected OfdpaSetVlanVid() {
44 + vlanId = null;
45 + }
46 +
47 + /**
48 + * Constructs a new set VLAN ID instruction with given VLAN ID.
49 + *
50 + * @param vlanId VLAN ID
51 + */
52 + public OfdpaSetVlanVid(VlanId vlanId) {
53 + checkNotNull(vlanId);
54 + this.vlanId = vlanId;
55 + }
56 +
57 + /**
58 + * Gets the VLAN ID.
59 + *
60 + * @return VLAN ID
61 + */
62 + public VlanId vlanId() {
63 + return vlanId;
64 + }
65 +
66 + @Override
67 + public ExtensionTreatmentType type() {
68 + return ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_VLAN_ID.type();
69 + }
70 +
71 + @Override
72 + public void deserialize(byte[] data) {
73 + vlanId = APPKRYO.deserialize(data);
74 + }
75 +
76 + @Override
77 + public byte[] serialize() {
78 + return APPKRYO.serialize(vlanId);
79 + }
80 +
81 + @Override
82 + public int hashCode() {
83 + return Objects.hash(vlanId);
84 + }
85 +
86 + @Override
87 + public boolean equals(Object obj) {
88 + if (this == obj) {
89 + return true;
90 + }
91 + if (obj instanceof OfdpaSetVlanVid) {
92 + OfdpaSetVlanVid that = (OfdpaSetVlanVid) obj;
93 + return Objects.equals(vlanId, that.vlanId);
94 +
95 + }
96 + return false;
97 + }
98 +
99 + @Override
100 + public String toString() {
101 + return MoreObjects.toStringHelper(getClass())
102 + .add("vlanId", vlanId)
103 + .toString();
104 + }
105 +}
...@@ -29,11 +29,14 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -29,11 +29,14 @@ import java.util.concurrent.ConcurrentHashMap;
29 29
30 import org.onlab.osgi.ServiceDirectory; 30 import org.onlab.osgi.ServiceDirectory;
31 import org.onlab.packet.Ethernet; 31 import org.onlab.packet.Ethernet;
32 +import org.onlab.packet.IpPrefix;
32 import org.onlab.packet.MacAddress; 33 import org.onlab.packet.MacAddress;
33 import org.onlab.packet.VlanId; 34 import org.onlab.packet.VlanId;
34 import org.onlab.util.KryoNamespace; 35 import org.onlab.util.KryoNamespace;
35 import org.onosproject.core.ApplicationId; 36 import org.onosproject.core.ApplicationId;
36 import org.onosproject.core.CoreService; 37 import org.onosproject.core.CoreService;
38 +import org.onosproject.driver.extensions.OfdpaMatchVlanVid;
39 +import org.onosproject.driver.extensions.OfdpaSetVlanVid;
37 import org.onosproject.net.DeviceId; 40 import org.onosproject.net.DeviceId;
38 import org.onosproject.net.Port; 41 import org.onosproject.net.Port;
39 import org.onosproject.net.PortNumber; 42 import org.onosproject.net.PortNumber;
...@@ -55,6 +58,7 @@ import org.onosproject.net.flow.criteria.Criteria; ...@@ -55,6 +58,7 @@ import org.onosproject.net.flow.criteria.Criteria;
55 import org.onosproject.net.flow.criteria.Criterion; 58 import org.onosproject.net.flow.criteria.Criterion;
56 import org.onosproject.net.flow.criteria.EthCriterion; 59 import org.onosproject.net.flow.criteria.EthCriterion;
57 import org.onosproject.net.flow.criteria.EthTypeCriterion; 60 import org.onosproject.net.flow.criteria.EthTypeCriterion;
61 +import org.onosproject.net.flow.criteria.ExtensionCriterion;
58 import org.onosproject.net.flow.criteria.IPCriterion; 62 import org.onosproject.net.flow.criteria.IPCriterion;
59 import org.onosproject.net.flow.criteria.MplsBosCriterion; 63 import org.onosproject.net.flow.criteria.MplsBosCriterion;
60 import org.onosproject.net.flow.criteria.MplsCriterion; 64 import org.onosproject.net.flow.criteria.MplsCriterion;
...@@ -65,6 +69,8 @@ import org.onosproject.net.flow.instructions.Instructions.OutputInstruction; ...@@ -65,6 +69,8 @@ import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
65 import org.onosproject.net.flow.instructions.L2ModificationInstruction; 69 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
66 import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType; 70 import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType;
67 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction; 71 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
72 +import org.onosproject.net.flow.instructions.L3ModificationInstruction;
73 +import org.onosproject.net.flow.instructions.L3ModificationInstruction.L3SubType;
68 import org.onosproject.net.flowobjective.FilteringObjective; 74 import org.onosproject.net.flowobjective.FilteringObjective;
69 import org.onosproject.net.flowobjective.FlowObjectiveStore; 75 import org.onosproject.net.flowobjective.FlowObjectiveStore;
70 import org.onosproject.net.flowobjective.ForwardingObjective; 76 import org.onosproject.net.flowobjective.ForwardingObjective;
...@@ -348,12 +354,39 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -348,12 +354,39 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
348 log.debug("filtering objective missing dstMac or VLAN, " 354 log.debug("filtering objective missing dstMac or VLAN, "
349 + "cannot program VLAN Table"); 355 + "cannot program VLAN Table");
350 } else { 356 } else {
351 - for (FlowRule vlanRule : processVlanIdFilter(portCriterion, vidCriterion, 357 + /*
352 - assignedVlan, 358 + * NOTE: Separate vlan filtering rules and assignment rules
353 - applicationId)) { 359 + * into different stage in order to guarantee that filtering rules
360 + * always go first.
361 + */
362 + List<FlowRule> allRules = processVlanIdFilter(
363 + portCriterion, vidCriterion, assignedVlan, applicationId);
364 + List<FlowRule> filteringRules = new ArrayList<>();
365 + List<FlowRule> assignmentRules = new ArrayList<>();
366 +
367 + allRules.forEach(flowRule -> {
368 + ExtensionCriterion extCriterion =
369 + (ExtensionCriterion) flowRule.selector().getCriterion(Criterion.Type.EXTENSION);
370 + VlanId vlanId = ((OfdpaMatchVlanVid) extCriterion.extensionSelector()).vlanId();
371 + if (vlanId.toShort() != (short) 0) {
372 + filteringRules.add(flowRule);
373 + } else {
374 + assignmentRules.add(flowRule);
375 + }
376 + });
377 +
378 + for (FlowRule filteringRule : filteringRules) {
354 log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}", 379 log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}",
355 - vlanRule, deviceId); 380 + filteringRule, deviceId);
356 - ops = install ? ops.add(vlanRule) : ops.remove(vlanRule); 381 + ops = install ? ops.add(filteringRule) : ops.remove(filteringRule);
382 + }
383 +
384 + ops.newStage();
385 +
386 + for (FlowRule assignmentRule : assignmentRules) {
387 + log.debug("adding VLAN assignment rule in VLAN table: {} for dev: {}",
388 + assignmentRule, deviceId);
389 + ops = install ? ops.add(assignmentRule) : ops.remove(assignmentRule);
357 } 390 }
358 } 391 }
359 392
...@@ -415,27 +448,41 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -415,27 +448,41 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
415 VlanIdCriterion vidCriterion, 448 VlanIdCriterion vidCriterion,
416 VlanId assignedVlan, 449 VlanId assignedVlan,
417 ApplicationId applicationId) { 450 ApplicationId applicationId) {
418 - List<FlowRule> rules = new ArrayList<FlowRule>(); 451 + List<FlowRule> rules = new ArrayList<>();
419 TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); 452 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
420 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); 453 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
421 - selector.matchVlanId(vidCriterion.vlanId()); 454 + TrafficSelector.Builder preSelector = null;
455 + TrafficTreatment.Builder preTreatment = null;
456 +
457 +
422 treatment.transition(TMAC_TABLE); 458 treatment.transition(TMAC_TABLE);
423 459
424 VlanId storeVlan = null; 460 VlanId storeVlan = null;
425 if (vidCriterion.vlanId() == VlanId.NONE) { 461 if (vidCriterion.vlanId() == VlanId.NONE) {
426 // untagged packets are assigned vlans 462 // untagged packets are assigned vlans
427 - treatment.pushVlan().setVlanId(assignedVlan); 463 + OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(VlanId.vlanId((short) 0));
464 + selector.extension(ofdpaMatchVlanVid, deviceId);
465 + OfdpaSetVlanVid ofdpaSetVlanVid = new OfdpaSetVlanVid(assignedVlan);
466 + treatment.extension(ofdpaSetVlanVid, deviceId);
428 // XXX ofdpa will require an additional vlan match on the assigned vlan 467 // XXX ofdpa will require an additional vlan match on the assigned vlan
429 // and it may not require the push. This is not in compliance with OF 468 // and it may not require the push. This is not in compliance with OF
430 // standard. Waiting on what the exact flows are going to look like. 469 // standard. Waiting on what the exact flows are going to look like.
431 storeVlan = assignedVlan; 470 storeVlan = assignedVlan;
471 +
472 + preSelector = DefaultTrafficSelector.builder();
473 + OfdpaMatchVlanVid preOfdpaMatchVlanVid = new OfdpaMatchVlanVid(assignedVlan);
474 + preSelector.extension(preOfdpaMatchVlanVid, deviceId);
475 + preTreatment = DefaultTrafficTreatment.builder().transition(TMAC_TABLE);
476 +
432 } else { 477 } else {
478 + OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(vidCriterion.vlanId());
479 + selector.extension(ofdpaMatchVlanVid, deviceId);
433 storeVlan = vidCriterion.vlanId(); 480 storeVlan = vidCriterion.vlanId();
434 } 481 }
435 482
436 // ofdpa cannot match on ALL portnumber, so we need to use separate 483 // ofdpa cannot match on ALL portnumber, so we need to use separate
437 // rules for each port. 484 // rules for each port.
438 - List<PortNumber> portnums = new ArrayList<PortNumber>(); 485 + List<PortNumber> portnums = new ArrayList<>();
439 if (portCriterion.port() == PortNumber.ALL) { 486 if (portCriterion.port() == PortNumber.ALL) {
440 for (Port port : deviceService.getPorts(deviceId)) { 487 for (Port port : deviceService.getPorts(deviceId)) {
441 if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) { 488 if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
...@@ -468,6 +515,20 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -468,6 +515,20 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
468 .fromApp(applicationId) 515 .fromApp(applicationId)
469 .makePermanent() 516 .makePermanent()
470 .forTable(VLAN_TABLE).build(); 517 .forTable(VLAN_TABLE).build();
518 +
519 + if (preSelector != null) {
520 + preSelector.matchInPort(pnum);
521 + FlowRule preRule = DefaultFlowRule.builder()
522 + .forDevice(deviceId)
523 + .withSelector(preSelector.build())
524 + .withTreatment(preTreatment.build())
525 + .withPriority(DEFAULT_PRIORITY)
526 + .fromApp(applicationId)
527 + .makePermanent()
528 + .forTable(VLAN_TABLE).build();
529 + rules.add(preRule);
530 + }
531 +
471 rules.add(rule); 532 rules.add(rule);
472 } 533 }
473 return rules; 534 return rules;
...@@ -509,11 +570,12 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -509,11 +570,12 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
509 570
510 List<FlowRule> rules = new ArrayList<FlowRule>(); 571 List<FlowRule> rules = new ArrayList<FlowRule>();
511 for (PortNumber pnum : portnums) { 572 for (PortNumber pnum : portnums) {
573 + OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(vidCriterion.vlanId());
512 // for unicast IP packets 574 // for unicast IP packets
513 TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); 575 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
514 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); 576 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
515 selector.matchInPort(pnum); 577 selector.matchInPort(pnum);
516 - selector.matchVlanId(vidCriterion.vlanId()); 578 + selector.extension(ofdpaMatchVlanVid, deviceId);
517 selector.matchEthType(Ethernet.TYPE_IPV4); 579 selector.matchEthType(Ethernet.TYPE_IPV4);
518 selector.matchEthDst(ethCriterion.mac()); 580 selector.matchEthDst(ethCriterion.mac());
519 treatment.transition(UNICAST_ROUTING_TABLE); 581 treatment.transition(UNICAST_ROUTING_TABLE);
...@@ -530,7 +592,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -530,7 +592,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
530 selector = DefaultTrafficSelector.builder(); 592 selector = DefaultTrafficSelector.builder();
531 treatment = DefaultTrafficTreatment.builder(); 593 treatment = DefaultTrafficTreatment.builder();
532 selector.matchInPort(pnum); 594 selector.matchInPort(pnum);
533 - selector.matchVlanId(vidCriterion.vlanId()); 595 + selector.extension(ofdpaMatchVlanVid, deviceId);
534 selector.matchEthType(Ethernet.MPLS_UNICAST); 596 selector.matchEthType(Ethernet.MPLS_UNICAST);
535 selector.matchEthDst(ethCriterion.mac()); 597 selector.matchEthDst(ethCriterion.mac());
536 treatment.transition(MPLS_TABLE_0); 598 treatment.transition(MPLS_TABLE_0);
...@@ -697,13 +759,27 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -697,13 +759,27 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
697 759
698 int forTableId; 760 int forTableId;
699 TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder(); 761 TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder();
762 + TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
763 + boolean popMpls = false;
764 +
700 if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) { 765 if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
766 + IpPrefix ipPrefix = ((IPCriterion)
767 + selector.getCriterion(Criterion.Type.IPV4_DST)).ip();
701 filteredSelector.matchEthType(Ethernet.TYPE_IPV4) 768 filteredSelector.matchEthType(Ethernet.TYPE_IPV4)
702 - .matchIPDst(((IPCriterion) 769 + .matchIPDst(ipPrefix);
703 - selector.getCriterion(Criterion.Type.IPV4_DST)).ip());
704 forTableId = UNICAST_ROUTING_TABLE; 770 forTableId = UNICAST_ROUTING_TABLE;
705 log.debug("processing IPv4 specific forwarding objective {} -> next:{}" 771 log.debug("processing IPv4 specific forwarding objective {} -> next:{}"
706 + " in dev:{}", fwd.id(), fwd.nextId(), deviceId); 772 + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
773 +
774 + if (fwd.treatment() != null) {
775 + for (Instruction instr : fwd.treatment().allInstructions()) {
776 + if (instr instanceof L3ModificationInstruction &&
777 + ((L3ModificationInstruction) instr).subtype() == L3SubType.DEC_TTL) {
778 + tb.deferred().add(instr);
779 + }
780 + }
781 + }
782 +
707 } else { 783 } else {
708 filteredSelector 784 filteredSelector
709 .matchEthType(Ethernet.MPLS_UNICAST) 785 .matchEthType(Ethernet.MPLS_UNICAST)
...@@ -717,20 +793,23 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -717,20 +793,23 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
717 forTableId = MPLS_TABLE_1; 793 forTableId = MPLS_TABLE_1;
718 log.debug("processing MPLS specific forwarding objective {} -> next:{}" 794 log.debug("processing MPLS specific forwarding objective {} -> next:{}"
719 + " in dev {}", fwd.id(), fwd.nextId(), deviceId); 795 + " in dev {}", fwd.id(), fwd.nextId(), deviceId);
720 - }
721 796
722 - TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); 797 + if (fwd.treatment() != null) {
723 - boolean popMpls = false; 798 + for (Instruction instr : fwd.treatment().allInstructions()) {
724 - if (fwd.treatment() != null) { 799 + if (instr instanceof L2ModificationInstruction &&
725 - for (Instruction i : fwd.treatment().allInstructions()) { 800 + ((L2ModificationInstruction) instr).subtype() == L2SubType.MPLS_POP) {
726 - /*
727 - * NOTE: OF-DPA does not support immediate instruction in
728 - * L3 unicast and MPLS table.
729 - */
730 - tb.deferred().add(i);
731 - if (i instanceof L2ModificationInstruction &&
732 - ((L2ModificationInstruction) i).subtype() == L2SubType.MPLS_POP) {
733 popMpls = true; 801 popMpls = true;
802 + tb.immediate().add(instr);
803 + }
804 + if (instr instanceof L3ModificationInstruction &&
805 + ((L3ModificationInstruction) instr).subtype() == L3SubType.DEC_TTL) {
806 + // FIXME Should modify the app to send the correct DEC_MPLS_TTL instruction
807 + tb.immediate().decMplsTtl();
808 + }
809 + if (instr instanceof L3ModificationInstruction &&
810 + ((L3ModificationInstruction) instr).subtype() == L3SubType.TTL_IN) {
811 + tb.immediate().add(instr);
812 + }
734 } 813 }
735 } 814 }
736 } 815 }
...@@ -817,7 +896,8 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -817,7 +896,8 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
817 + "in dev:{} for vlan:{}", 896 + "in dev:{} for vlan:{}",
818 fwd.id(), fwd.nextId(), deviceId, vlanIdCriterion.vlanId()); 897 fwd.id(), fwd.nextId(), deviceId, vlanIdCriterion.vlanId());
819 } 898 }
820 - filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId()); 899 + OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(vlanIdCriterion.vlanId());
900 + filteredSelectorBuilder.extension(ofdpaMatchVlanVid, deviceId);
821 TrafficSelector filteredSelector = filteredSelectorBuilder.build(); 901 TrafficSelector filteredSelector = filteredSelectorBuilder.build();
822 902
823 if (fwd.treatment() != null) { 903 if (fwd.treatment() != null) {
......
...@@ -92,6 +92,14 @@ ...@@ -92,6 +92,14 @@
92 manufacturer="Broadcom Corp." hwVersion="OF-DPA.*" swVersion="OF-DPA.*"> 92 manufacturer="Broadcom Corp." hwVersion="OF-DPA.*" swVersion="OF-DPA.*">
93 <behaviour api="org.onosproject.net.behaviour.Pipeliner" 93 <behaviour api="org.onosproject.net.behaviour.Pipeliner"
94 impl="org.onosproject.driver.pipeline.OFDPA2Pipeline"/> 94 impl="org.onosproject.driver.pipeline.OFDPA2Pipeline"/>
95 + <behaviour api="org.onosproject.openflow.controller.ExtensionTreatmentInterpreter"
96 + impl="org.onosproject.driver.extensions.OfdpaExtensionTreatmentInterpreter" />
97 + <behaviour api="org.onosproject.net.behaviour.ExtensionTreatmentResolver"
98 + impl="org.onosproject.driver.extensions.OfdpaExtensionTreatmentInterpreter" />
99 + <behaviour api="org.onosproject.openflow.controller.ExtensionSelectorInterpreter"
100 + impl="org.onosproject.driver.extensions.OfdpaExtensionSelectorInterpreter" />
101 + <behaviour api="org.onosproject.net.behaviour.ExtensionSelectorResolver"
102 + impl="org.onosproject.driver.extensions.OfdpaExtensionSelectorInterpreter" />
95 </driver> 103 </driver>
96 <driver name="pmc-olt" extends="default" 104 <driver name="pmc-olt" extends="default"
97 manufacturer="PMC GPON Networks" hwVersion="PASffffffff v-1" swVersion="vOLT.*"> 105 manufacturer="PMC GPON Networks" hwVersion="PASffffffff v-1" swVersion="vOLT.*">
......
...@@ -43,7 +43,7 @@ public interface ExtensionSelectorInterpreter extends HandlerBehaviour { ...@@ -43,7 +43,7 @@ public interface ExtensionSelectorInterpreter extends HandlerBehaviour {
43 * 43 *
44 * @param factory OpenFlow factory 44 * @param factory OpenFlow factory
45 * @param extensionSelector extension selector 45 * @param extensionSelector extension selector
46 - * @return OpenFlow action 46 + * @return OpenFlow OXM
47 */ 47 */
48 OFOxm<?> mapSelector(OFFactory factory, ExtensionSelector extensionSelector); 48 OFOxm<?> mapSelector(OFFactory factory, ExtensionSelector extensionSelector);
49 49
......
...@@ -43,12 +43,16 @@ import org.onosproject.net.flow.FlowEntry.FlowEntryState; ...@@ -43,12 +43,16 @@ import org.onosproject.net.flow.FlowEntry.FlowEntryState;
43 import org.onosproject.net.flow.FlowRule; 43 import org.onosproject.net.flow.FlowRule;
44 import org.onosproject.net.flow.TrafficSelector; 44 import org.onosproject.net.flow.TrafficSelector;
45 import org.onosproject.net.flow.TrafficTreatment; 45 import org.onosproject.net.flow.TrafficTreatment;
46 +import org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes;
47 +import org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes;
46 import org.onosproject.net.flow.instructions.Instructions; 48 import org.onosproject.net.flow.instructions.Instructions;
47 import org.onosproject.openflow.controller.Dpid; 49 import org.onosproject.openflow.controller.Dpid;
50 +import org.onosproject.openflow.controller.ExtensionSelectorInterpreter;
48 import org.onosproject.openflow.controller.ExtensionTreatmentInterpreter; 51 import org.onosproject.openflow.controller.ExtensionTreatmentInterpreter;
49 import org.projectfloodlight.openflow.protocol.OFFlowMod; 52 import org.projectfloodlight.openflow.protocol.OFFlowMod;
50 import org.projectfloodlight.openflow.protocol.OFFlowRemoved; 53 import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
51 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry; 54 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
55 +import org.projectfloodlight.openflow.protocol.OFMatchV3;
52 import org.projectfloodlight.openflow.protocol.OFVersion; 56 import org.projectfloodlight.openflow.protocol.OFVersion;
53 import org.projectfloodlight.openflow.protocol.action.OFAction; 57 import org.projectfloodlight.openflow.protocol.action.OFAction;
54 import org.projectfloodlight.openflow.protocol.action.OFActionCircuit; 58 import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
...@@ -137,7 +141,6 @@ public class FlowEntryBuilder { ...@@ -137,7 +141,6 @@ public class FlowEntryBuilder {
137 public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed, DriverService driverService) { 141 public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed, DriverService driverService) {
138 this.match = removed.getMatch(); 142 this.match = removed.getMatch();
139 this.removed = removed; 143 this.removed = removed;
140 -
141 this.dpid = dpid; 144 this.dpid = dpid;
142 this.instructions = null; 145 this.instructions = null;
143 this.stat = null; 146 this.stat = null;
...@@ -288,6 +291,14 @@ public class FlowEntryBuilder { ...@@ -288,6 +291,14 @@ public class FlowEntryBuilder {
288 291
289 private TrafficTreatment.Builder buildActions(List<OFAction> actions, 292 private TrafficTreatment.Builder buildActions(List<OFAction> actions,
290 TrafficTreatment.Builder builder) { 293 TrafficTreatment.Builder builder) {
294 + DriverHandler driverHandler = getDriver(dpid);
295 + ExtensionTreatmentInterpreter treatmentInterpreter;
296 + if (driverHandler.hasBehaviour(ExtensionTreatmentInterpreter.class)) {
297 + treatmentInterpreter = driverHandler.behaviour(ExtensionTreatmentInterpreter.class);
298 + } else {
299 + treatmentInterpreter = null;
300 + }
301 +
291 for (OFAction act : actions) { 302 for (OFAction act : actions) {
292 switch (act.getType()) { 303 switch (act.getType()) {
293 case OUTPUT: 304 case OUTPUT:
...@@ -312,7 +323,6 @@ public class FlowEntryBuilder { ...@@ -312,7 +323,6 @@ public class FlowEntryBuilder {
312 OFActionSetDlSrc dlsrc = (OFActionSetDlSrc) act; 323 OFActionSetDlSrc dlsrc = (OFActionSetDlSrc) act;
313 builder.setEthSrc( 324 builder.setEthSrc(
314 MacAddress.valueOf(dlsrc.getDlAddr().getLong())); 325 MacAddress.valueOf(dlsrc.getDlAddr().getLong()));
315 -
316 break; 326 break;
317 case SET_NW_DST: 327 case SET_NW_DST:
318 OFActionSetNwDst nwdst = (OFActionSetNwDst) act; 328 OFActionSetNwDst nwdst = (OFActionSetNwDst) act;
...@@ -332,11 +342,8 @@ public class FlowEntryBuilder { ...@@ -332,11 +342,8 @@ public class FlowEntryBuilder {
332 short lambda = ((OFOxmOchSigidBasic) ct.getField()).getValue().getChannelNumber(); 342 short lambda = ((OFOxmOchSigidBasic) ct.getField()).getValue().getChannelNumber();
333 builder.add(Instructions.modL0Lambda(Lambda.indexedLambda(lambda))); 343 builder.add(Instructions.modL0Lambda(Lambda.indexedLambda(lambda)));
334 } else if (exp.getExperimenter() == 0x2320) { 344 } else if (exp.getExperimenter() == 0x2320) {
335 - DriverHandler driver = getDriver(dpid); 345 + if (treatmentInterpreter != null) {
336 - ExtensionTreatmentInterpreter interpreter = driver 346 + builder.extension(treatmentInterpreter.mapAction(exp),
337 - .behaviour(ExtensionTreatmentInterpreter.class);
338 - if (interpreter != null) {
339 - builder.extension(interpreter.mapAction(exp),
340 DeviceId.deviceId(Dpid.uri(dpid))); 347 DeviceId.deviceId(Dpid.uri(dpid)));
341 } 348 }
342 } else { 349 } else {
...@@ -405,6 +412,14 @@ public class FlowEntryBuilder { ...@@ -405,6 +412,14 @@ public class FlowEntryBuilder {
405 412
406 413
407 private void handleSetField(TrafficTreatment.Builder builder, OFActionSetField action) { 414 private void handleSetField(TrafficTreatment.Builder builder, OFActionSetField action) {
415 + DriverHandler driverHandler = getDriver(dpid);
416 + ExtensionTreatmentInterpreter treatmentInterpreter;
417 + if (driverHandler.hasBehaviour(ExtensionTreatmentInterpreter.class)) {
418 + treatmentInterpreter = driverHandler.behaviour(ExtensionTreatmentInterpreter.class);
419 + } else {
420 + treatmentInterpreter = null;
421 + }
422 +
408 OFOxm<?> oxm = action.getField(); 423 OFOxm<?> oxm = action.getField();
409 switch (oxm.getMatchField().id) { 424 switch (oxm.getMatchField().id) {
410 case VLAN_PCP: 425 case VLAN_PCP:
...@@ -413,9 +428,15 @@ public class FlowEntryBuilder { ...@@ -413,9 +428,15 @@ public class FlowEntryBuilder {
413 builder.setVlanPcp(vlanpcp.getValue().getValue()); 428 builder.setVlanPcp(vlanpcp.getValue().getValue());
414 break; 429 break;
415 case VLAN_VID: 430 case VLAN_VID:
416 - @SuppressWarnings("unchecked") 431 + if (treatmentInterpreter != null &&
417 - OFOxm<OFVlanVidMatch> vlanvid = (OFOxm<OFVlanVidMatch>) oxm; 432 + treatmentInterpreter.supported(ExtensionTreatmentTypes.OFDPA_SET_VLAN_ID.type())) {
418 - builder.setVlanId(VlanId.vlanId(vlanvid.getValue().getVlan())); 433 + builder.extension(treatmentInterpreter.mapAction(action),
434 + DeviceId.deviceId(Dpid.uri(dpid)));
435 + } else {
436 + @SuppressWarnings("unchecked")
437 + OFOxm<OFVlanVidMatch> vlanvid = (OFOxm<OFVlanVidMatch>) oxm;
438 + builder.setVlanId(VlanId.vlanId(vlanvid.getValue().getVlan()));
439 + }
419 break; 440 break;
420 case ETH_DST: 441 case ETH_DST:
421 @SuppressWarnings("unchecked") 442 @SuppressWarnings("unchecked")
...@@ -475,10 +496,9 @@ public class FlowEntryBuilder { ...@@ -475,10 +496,9 @@ public class FlowEntryBuilder {
475 builder.setUdpSrc(TpPort.tpPort(udpsrc.getValue().getPort())); 496 builder.setUdpSrc(TpPort.tpPort(udpsrc.getValue().getPort()));
476 break; 497 break;
477 case TUNNEL_IPV4_DST: 498 case TUNNEL_IPV4_DST:
478 - DriverHandler driver = getDriver(dpid); 499 + if (treatmentInterpreter != null &&
479 - ExtensionTreatmentInterpreter interpreter = driver.behaviour(ExtensionTreatmentInterpreter.class); 500 + treatmentInterpreter.supported(ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type())) {
480 - if (interpreter != null) { 501 + builder.extension(treatmentInterpreter.mapAction(action), DeviceId.deviceId(Dpid.uri(dpid)));
481 - builder.extension(interpreter.mapAction(action), DeviceId.deviceId(Dpid.uri(dpid)));
482 } 502 }
483 break; 503 break;
484 case EXP_ODU_SIG_ID: 504 case EXP_ODU_SIG_ID:
...@@ -567,6 +587,14 @@ public class FlowEntryBuilder { ...@@ -567,6 +587,14 @@ public class FlowEntryBuilder {
567 Ip6Prefix ip6Prefix; 587 Ip6Prefix ip6Prefix;
568 Ip4Address ip; 588 Ip4Address ip;
569 589
590 + DriverHandler driverHandler = getDriver(dpid);
591 + ExtensionSelectorInterpreter selectorInterpreter;
592 + if (driverHandler.hasBehaviour(ExtensionSelectorInterpreter.class)) {
593 + selectorInterpreter = driverHandler.behaviour(ExtensionSelectorInterpreter.class);
594 + } else {
595 + selectorInterpreter = null;
596 + }
597 +
570 TrafficSelector.Builder builder = DefaultTrafficSelector.builder(); 598 TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
571 for (MatchField<?> field : match.getMatchFields()) { 599 for (MatchField<?> field : match.getMatchFields()) {
572 switch (field.id) { 600 switch (field.id) {
...@@ -596,22 +624,33 @@ public class FlowEntryBuilder { ...@@ -596,22 +624,33 @@ public class FlowEntryBuilder {
596 builder.matchEthType((short) ethType); 624 builder.matchEthType((short) ethType);
597 break; 625 break;
598 case VLAN_VID: 626 case VLAN_VID:
599 - VlanId vlanId = null; 627 + if (selectorInterpreter != null &&
600 - if (match.isPartiallyMasked(MatchField.VLAN_VID)) { 628 + selectorInterpreter.supported(ExtensionSelectorTypes.OFDPA_MATCH_VLAN_VID.type())) {
601 - Masked<OFVlanVidMatch> masked = match.getMasked(MatchField.VLAN_VID); 629 + if (match.getVersion().equals(OFVersion.OF_13)) {
602 - if (masked.getValue().equals(OFVlanVidMatch.PRESENT) 630 + OFOxm oxm = ((OFMatchV3) match).getOxmList().get(MatchField.VLAN_VID);
603 - && masked.getMask().equals(OFVlanVidMatch.PRESENT)) { 631 + builder.extension(selectorInterpreter.mapOxm(oxm),
604 - vlanId = VlanId.ANY; 632 + DeviceId.deviceId(Dpid.uri(dpid)));
633 + } else {
634 + break;
605 } 635 }
606 } else { 636 } else {
607 - if (!match.get(MatchField.VLAN_VID).isPresentBitSet()) { 637 + VlanId vlanId = null;
608 - vlanId = VlanId.NONE; 638 + if (match.isPartiallyMasked(MatchField.VLAN_VID)) {
639 + Masked<OFVlanVidMatch> masked = match.getMasked(MatchField.VLAN_VID);
640 + if (masked.getValue().equals(OFVlanVidMatch.PRESENT)
641 + && masked.getMask().equals(OFVlanVidMatch.PRESENT)) {
642 + vlanId = VlanId.ANY;
643 + }
609 } else { 644 } else {
610 - vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan()); 645 + if (!match.get(MatchField.VLAN_VID).isPresentBitSet()) {
646 + vlanId = VlanId.NONE;
647 + } else {
648 + vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
649 + }
650 + }
651 + if (vlanId != null) {
652 + builder.matchVlanId(vlanId);
611 } 653 }
612 - }
613 - if (vlanId != null) {
614 - builder.matchVlanId(vlanId);
615 } 654 }
616 break; 655 break;
617 case VLAN_PCP: 656 case VLAN_PCP:
......
...@@ -240,7 +240,7 @@ public abstract class FlowModBuilder { ...@@ -240,7 +240,7 @@ public abstract class FlowModBuilder {
240 mBuilder.setExact(MatchField.VLAN_VID, OFVlanVidMatch.NONE); 240 mBuilder.setExact(MatchField.VLAN_VID, OFVlanVidMatch.NONE);
241 } else { 241 } else {
242 mBuilder.setExact(MatchField.VLAN_VID, 242 mBuilder.setExact(MatchField.VLAN_VID,
243 - OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort()))); 243 + OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort())));
244 } 244 }
245 break; 245 break;
246 case VLAN_PCP: 246 case VLAN_PCP:
......
...@@ -20,6 +20,7 @@ import com.google.common.base.Objects; ...@@ -20,6 +20,7 @@ import com.google.common.base.Objects;
20 import com.google.common.collect.ImmutableSet; 20 import com.google.common.collect.ImmutableSet;
21 import com.google.common.collect.Maps; 21 import com.google.common.collect.Maps;
22 import com.google.common.collect.Sets; 22 import com.google.common.collect.Sets;
23 +import org.onosproject.net.driver.DriverService;
23 import org.onosproject.net.flow.DefaultTypedFlowEntry; 24 import org.onosproject.net.flow.DefaultTypedFlowEntry;
24 import org.onosproject.net.flow.FlowEntry; 25 import org.onosproject.net.flow.FlowEntry;
25 import org.onosproject.net.flow.FlowId; 26 import org.onosproject.net.flow.FlowId;
...@@ -55,9 +56,9 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -55,9 +56,9 @@ import static org.slf4j.LoggerFactory.getLogger;
55 * Efficiently and adaptively collects flow statistics for the specified switch. 56 * Efficiently and adaptively collects flow statistics for the specified switch.
56 */ 57 */
57 public class NewAdaptiveFlowStatsCollector { 58 public class NewAdaptiveFlowStatsCollector {
58 -
59 private final Logger log = getLogger(getClass()); 59 private final Logger log = getLogger(getClass());
60 60
61 + private final DriverService driverService;
61 private final OpenFlowSwitch sw; 62 private final OpenFlowSwitch sw;
62 63
63 private ScheduledExecutorService adaptiveFlowStatsScheduler = 64 private ScheduledExecutorService adaptiveFlowStatsScheduler =
...@@ -109,9 +110,10 @@ public class NewAdaptiveFlowStatsCollector { ...@@ -109,9 +110,10 @@ public class NewAdaptiveFlowStatsCollector {
109 * @param sw switch to pull 110 * @param sw switch to pull
110 * @param pollInterval cal and immediate poll frequency in seconds 111 * @param pollInterval cal and immediate poll frequency in seconds
111 */ 112 */
112 - NewAdaptiveFlowStatsCollector(OpenFlowSwitch sw, int pollInterval) { 113 + NewAdaptiveFlowStatsCollector(
114 + DriverService driverService, OpenFlowSwitch sw, int pollInterval) {
115 + this.driverService = driverService;
113 this.sw = sw; 116 this.sw = sw;
114 -
115 initMemberVars(pollInterval); 117 initMemberVars(pollInterval);
116 } 118 }
117 119
...@@ -232,7 +234,7 @@ public class NewAdaptiveFlowStatsCollector { ...@@ -232,7 +234,7 @@ public class NewAdaptiveFlowStatsCollector {
232 private void ofFlowStatsRequestFlowSend(FlowEntry fe) { 234 private void ofFlowStatsRequestFlowSend(FlowEntry fe) {
233 // set find match 235 // set find match
234 Match match = FlowModBuilder.builder(fe, sw.factory(), Optional.empty(), 236 Match match = FlowModBuilder.builder(fe, sw.factory(), Optional.empty(),
235 - Optional.empty()).buildMatch(); 237 + Optional.of(driverService)).buildMatch();
236 // set find tableId 238 // set find tableId
237 TableId tableId = TableId.of(fe.tableId()); 239 TableId tableId = TableId.of(fe.tableId());
238 // set output port 240 // set output port
......
...@@ -219,7 +219,8 @@ public class OpenFlowRuleProvider extends AbstractProvider ...@@ -219,7 +219,8 @@ public class OpenFlowRuleProvider extends AbstractProvider
219 private void createCollector(OpenFlowSwitch sw) { 219 private void createCollector(OpenFlowSwitch sw) {
220 if (adaptiveFlowSampling) { 220 if (adaptiveFlowSampling) {
221 // NewAdaptiveFlowStatsCollector Constructor 221 // NewAdaptiveFlowStatsCollector Constructor
222 - NewAdaptiveFlowStatsCollector fsc = new NewAdaptiveFlowStatsCollector(sw, flowPollFrequency); 222 + NewAdaptiveFlowStatsCollector fsc =
223 + new NewAdaptiveFlowStatsCollector(driverService, sw, flowPollFrequency);
223 fsc.start(); 224 fsc.start();
224 afsCollectors.put(new Dpid(sw.getId()), fsc); 225 afsCollectors.put(new Dpid(sw.getId()), fsc);
225 } else { 226 } else {
......
...@@ -211,10 +211,12 @@ public class OpenFlowMeterProvider extends AbstractProvider implements MeterProv ...@@ -211,10 +211,12 @@ public class OpenFlowMeterProvider extends AbstractProvider implements MeterProv
211 } 211 }
212 } 212 }
213 213
214 + // TODO: ONOS-3546 Support per device enabling/disabling via network config
214 private boolean isMeterSupported(OpenFlowSwitch sw) { 215 private boolean isMeterSupported(OpenFlowSwitch sw) {
215 if (sw.factory().getVersion() == OFVersion.OF_10 || 216 if (sw.factory().getVersion() == OFVersion.OF_10 ||
216 sw.factory().getVersion() == OFVersion.OF_11 || 217 sw.factory().getVersion() == OFVersion.OF_11 ||
217 - sw.factory().getVersion() == OFVersion.OF_12) { 218 + sw.factory().getVersion() == OFVersion.OF_12 ||
219 + sw.softwareDescription().equals("OF-DPA 2.0")) {
218 return false; 220 return false;
219 } 221 }
220 222
......