[ONOS-2831] Refactor L2 code according to the L3 plan.
Change-Id: Ibc9dc47a18208b9b1602261064a33bc63b131fc3
diff --git a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ClassifierService.java b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ClassifierService.java
new file mode 100644
index 0000000..84fcefb
--- /dev/null
+++ b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ClassifierService.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table;
+
+import org.onlab.packet.MacAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtnrsc.SegmentationId;
+
+/**
+ * Applies classifier flows to the device.
+ */
+public interface ClassifierService {
+
+ /**
+ * The port rule that message from host matches Table(0) Match: host mac and
+ * ingress port Action: set vnid and go to table(50).
+ *
+ * @param deviceId Device Id
+ * @param segmentationId the vnid of the host belong to
+ * @param inPort the ingress port of the host
+ * @param srcMac the mac of the host
+ * @param appId the application ID of the vtn
+ * @param type the operation of the flow
+ */
+ void programLocalIn(DeviceId deviceId, SegmentationId segmentationId,
+ PortNumber inPort, MacAddress srcMac,
+ ApplicationId appId, Objective.Operation type);
+
+ /**
+ * The port rule that message from tunnel Table(0) Match: tunnel port and
+ * vnid Action: go to table(50).
+ *
+ * @param deviceId Device Id
+ * @param segmentationId the vnid of the host belong to
+ * @param localTunnelPorts the tunnel pors of the device
+ * @param type the operation of the flow
+ */
+ void programTunnelIn(DeviceId deviceId, SegmentationId segmentationId,
+ Iterable<PortNumber> localTunnelPorts,
+ Objective.Operation type);
+
+}
diff --git a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/L2ForwardService.java b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/L2ForwardService.java
new file mode 100644
index 0000000..3781c2b
--- /dev/null
+++ b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/L2ForwardService.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table;
+
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtnrsc.SegmentationId;
+
+/**
+ * Applies L2 flows to the device.
+ */
+public interface L2ForwardService {
+
+ /**
+ * The local broadcast rule that message matches Table(50) Match: broadcast
+ * mac and vnid Action: output port.
+ *
+ * @param deviceId Device Id
+ * @param segmentationId the vnid of the host belong to
+ * @param inPort the ingress port of the host
+ * @param localVmPorts the local ports of the network which connect host
+ * @param localTunnelPorts the tunnel pors of the device
+ * @param type the operation of the flow
+ */
+ void programLocalBcastRules(DeviceId deviceId,
+ SegmentationId segmentationId,
+ PortNumber inPort,
+ Iterable<PortNumber> localVmPorts,
+ Iterable<PortNumber> localTunnelPorts,
+ Objective.Operation type);
+
+ /**
+ * The tunnel broadcast rule that message matches Table(50) Match: broadcast
+ * mac and vnid Action: output port.
+ *
+ * @param deviceId Device Id
+ * @param segmentationId the vnid of the host belong to
+ * @param localVmPorts the local ports of the network which connect host
+ * @param localTunnelPorts the tunnel pors of the device
+ * @param type the operation of the flow
+ */
+ void programTunnelBcastRules(DeviceId deviceId,
+ SegmentationId segmentationId,
+ Iterable<PortNumber> localVmPorts,
+ Iterable<PortNumber> localTunnelPorts,
+ Objective.Operation type);
+
+ /**
+ * The local out rule that message matches. Table(50) Match: local host mac
+ * and vnid Action: output local host port.
+ *
+ * @param deviceId Device Id
+ * @param segmentationId the vnid of the host belong to
+ * @param outPort the ingress port of the host
+ * @param sourceMac the mac of the host
+ * @param type the operation of the flow
+ */
+ void programLocalOut(DeviceId deviceId, SegmentationId segmentationId,
+ PortNumber outPort, MacAddress sourceMac,
+ Objective.Operation type);
+
+ /**
+ * The tunnel out rule that message matches. Table(50) Match: host mac and
+ * vnid Action: output tunnel port.
+ *
+ * @param deviceId Device Id
+ * @param segmentationId the vnid of the host belong to
+ * @param tunnelOutPort the port of the tunnel
+ * @param dstMac the mac of the host
+ * @param type the operation of the flow
+ */
+ void programTunnelOut(DeviceId deviceId, SegmentationId segmentationId,
+ PortNumber tunnelOutPort, MacAddress dstMac,
+ Objective.Operation type);
+
+}
diff --git a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/ClassifierServiceImpl.java b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/ClassifierServiceImpl.java
new file mode 100644
index 0000000..620a0e9
--- /dev/null
+++ b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/ClassifierServiceImpl.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.MacAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtn.table.ClassifierService;
+import org.onosproject.vtnrsc.SegmentationId;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Provides implementation of ClassifierService.
+ */
+public class ClassifierServiceImpl implements ClassifierService {
+ private final Logger log = getLogger(getClass());
+
+ private static final int L2_CLAFFIFIER_PRIORITY = 50000;
+
+ private final FlowObjectiveService flowObjectiveService;
+ private final ApplicationId appId;
+
+ /**
+ * Constructor.
+ *
+ * @param appId the application id of vtn
+ */
+ public ClassifierServiceImpl(ApplicationId appId) {
+ this.appId = checkNotNull(appId, "ApplicationId can not be null");
+ ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+ this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
+ }
+
+ @Override
+ public void programLocalIn(DeviceId deviceId,
+ SegmentationId segmentationId, PortNumber inPort,
+ MacAddress srcMac, ApplicationId appid,
+ Objective.Operation type) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(inPort).matchEthSrc(srcMac).build();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.add(Instructions
+ .modTunnelId(Long.parseLong(segmentationId.toString())));
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment.build())
+ .withSelector(selector).fromApp(appId).makePermanent()
+ .withFlag(Flag.SPECIFIC).withPriority(L2_CLAFFIFIER_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ log.debug("programLocalIn-->ADD");
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ log.debug("programLocalIn-->REMOVE");
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ }
+
+ @Override
+ public void programTunnelIn(DeviceId deviceId,
+ SegmentationId segmentationId,
+ Iterable<PortNumber> localTunnelPorts,
+ Objective.Operation type) {
+ if (localTunnelPorts == null) {
+ log.info("No tunnel port in device");
+ return;
+ }
+ Sets.newHashSet(localTunnelPorts).stream().forEach(tp -> {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(tp).add(Criteria.matchTunnelId(Long
+ .parseLong(segmentationId.toString())))
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .build();
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment).withSelector(selector)
+ .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
+ .withPriority(L2_CLAFFIFIER_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ log.debug("programTunnelIn-->ADD");
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ log.debug("programTunnelIn-->REMOVE");
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ });
+ }
+
+}
diff --git a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/L2ForwardServiceImpl.java b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/L2ForwardServiceImpl.java
new file mode 100644
index 0000000..64c5fee
--- /dev/null
+++ b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/L2ForwardServiceImpl.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.MacAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtn.table.L2ForwardService;
+import org.onosproject.vtnrsc.SegmentationId;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Provides implementation of L2ForwardService.
+ */
+public final class L2ForwardServiceImpl implements L2ForwardService {
+ private final Logger log = getLogger(getClass());
+
+ private static final int MAC_PRIORITY = 0xffff;
+
+ private final FlowObjectiveService flowObjectiveService;
+ private final ApplicationId appId;
+
+ /**
+ * Constructor.
+ *
+ * @param appId the application id of vtn
+ */
+ public L2ForwardServiceImpl(ApplicationId appId) {
+ this.appId = checkNotNull(appId, "ApplicationId can not be null");
+ ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+ this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
+ }
+
+ @Override
+ public void programLocalBcastRules(DeviceId deviceId,
+ SegmentationId segmentationId,
+ PortNumber inPort,
+ Iterable<PortNumber> localVmPorts,
+ Iterable<PortNumber> localTunnelPorts,
+ Objective.Operation type) {
+ if (localVmPorts == null || localTunnelPorts == null) {
+ log.info("No other host port and tunnel in the device");
+ return;
+ }
+ Sets.newHashSet(localVmPorts).stream().forEach(lp -> {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(lp).matchEthDst(MacAddress.BROADCAST)
+ .add(Criteria.matchTunnelId(Long
+ .parseLong(segmentationId.toString())))
+ .build();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment
+ .builder();
+ boolean flag = false;
+ for (PortNumber outPort : localVmPorts) {
+ flag = true;
+ if (outPort != lp) {
+ treatment.setOutput(outPort);
+ }
+ }
+ if (type.equals(Objective.Operation.REMOVE) && inPort == lp) {
+ flag = false;
+ }
+ for (PortNumber outport : localTunnelPorts) {
+ treatment.setOutput(outport);
+ }
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment.build())
+ .withSelector(selector).fromApp(appId).makePermanent()
+ .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
+ if (flag) {
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ });
+ }
+
+ @Override
+ public void programTunnelBcastRules(DeviceId deviceId,
+ SegmentationId segmentationId,
+ Iterable<PortNumber> localVmPorts,
+ Iterable<PortNumber> localTunnelPorts,
+ Objective.Operation type) {
+ if (localVmPorts == null || localTunnelPorts == null) {
+ log.info("No other host port or tunnel ports in the device");
+ return;
+ }
+ Sets.newHashSet(localTunnelPorts).stream().forEach(tp -> {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(tp)
+ .add(Criteria.matchTunnelId(Long
+ .parseLong(segmentationId.toString())))
+ .matchEthDst(MacAddress.BROADCAST).build();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment
+ .builder();
+
+ for (PortNumber outPort : localVmPorts) {
+ treatment.setOutput(outPort);
+ }
+
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment.build())
+ .withSelector(selector).fromApp(appId).makePermanent()
+ .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ if (Sets.newHashSet(localVmPorts).size() == 0) {
+ flowObjectiveService.forward(deviceId, objective.remove());
+ } else {
+ flowObjectiveService.forward(deviceId, objective.add());
+ }
+ } else {
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ });
+ }
+
+ @Override
+ public void programLocalOut(DeviceId deviceId,
+ SegmentationId segmentationId,
+ PortNumber outPort, MacAddress sourceMac,
+ Objective.Operation type) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchTunnelId(Long.parseLong(segmentationId.toString()))
+ .matchEthDst(sourceMac).build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(outPort).build();
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment).withSelector(selector)
+ .fromApp(appId).withFlag(Flag.SPECIFIC)
+ .withPriority(MAC_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+
+ }
+
+ @Override
+ public void programTunnelOut(DeviceId deviceId,
+ SegmentationId segmentationId,
+ PortNumber tunnelOutPort, MacAddress dstMac,
+ Objective.Operation type) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthDst(dstMac).add(Criteria.matchTunnelId(Long
+ .parseLong(segmentationId.toString())))
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(tunnelOutPort).build();
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment).withSelector(selector)
+ .fromApp(appId).withFlag(Flag.SPECIFIC)
+ .withPriority(MAC_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+
+ }
+
+}
diff --git a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/package-info.java b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/package-info.java
new file mode 100644
index 0000000..fd2e18e
--- /dev/null
+++ b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * VTN application that applies configuration and flows to the device.
+ */
+package org.onosproject.vtn.table.impl;
diff --git a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/package-info.java b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/package-info.java
new file mode 100644
index 0000000..cf53c96
--- /dev/null
+++ b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * VTN application that applies configuration and flows to the device.
+ */
+package org.onosproject.vtn.table;