diff options
author | Ashlee Young <ashlee@onosfw.com> | 2015-09-09 22:15:21 -0700 |
---|---|---|
committer | Ashlee Young <ashlee@onosfw.com> | 2015-09-09 22:15:21 -0700 |
commit | 13d05bc8458758ee39cb829098241e89616717ee (patch) | |
tree | 22a4d1ce65f15952f07a3df5af4b462b4697cb3a /framework/src/onos/apps/cordfabric/src/main/java/org/onosproject/cordfabric/CordFabricManager.java | |
parent | 6139282e1e93c2322076de4b91b1c85d0bc4a8b3 (diff) |
ONOS checkin based on commit tag e796610b1f721d02f9b0e213cf6f7790c10ecd60
Change-Id: Ife8810491034fe7becdba75dda20de4267bd15cd
Diffstat (limited to 'framework/src/onos/apps/cordfabric/src/main/java/org/onosproject/cordfabric/CordFabricManager.java')
-rw-r--r-- | framework/src/onos/apps/cordfabric/src/main/java/org/onosproject/cordfabric/CordFabricManager.java | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/framework/src/onos/apps/cordfabric/src/main/java/org/onosproject/cordfabric/CordFabricManager.java b/framework/src/onos/apps/cordfabric/src/main/java/org/onosproject/cordfabric/CordFabricManager.java new file mode 100644 index 00000000..1523e9c2 --- /dev/null +++ b/framework/src/onos/apps/cordfabric/src/main/java/org/onosproject/cordfabric/CordFabricManager.java @@ -0,0 +1,433 @@ +/* + * 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.cordfabric; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onlab.packet.Ethernet; +import org.onlab.packet.IPv4; +import org.onlab.packet.MacAddress; +import org.onlab.packet.TpPort; +import org.onlab.packet.VlanId; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; +import org.onosproject.net.device.DeviceEvent; +import org.onosproject.net.device.DeviceListener; +import org.onosproject.net.device.DeviceService; +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.flowobjective.DefaultForwardingObjective; +import org.onosproject.net.flowobjective.FlowObjectiveService; +import org.onosproject.net.flowobjective.ForwardingObjective; +import org.onosproject.net.flowobjective.Objective; +import org.onosproject.net.flowobjective.ObjectiveContext; +import org.onosproject.net.flowobjective.ObjectiveError; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * CORD fabric application. + */ +@Service +@Component(immediate = true) +public class CordFabricManager implements FabricService { + + private final Logger log = getLogger(getClass()); + + private ApplicationId appId; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected FlowObjectiveService flowObjectiveService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected DeviceService deviceService; + + private InternalDeviceListener deviceListener = new InternalDeviceListener(); + + private static final int PRIORITY = 50000; + private static final int TESTPRIO = 49999; + + private short radiusPort = 1812; + + private short ofPort = 6633; + + private DeviceId fabricDeviceId = DeviceId.deviceId("of:5e3e486e73000187"); + + private final Multimap<VlanId, ConnectPoint> vlans = HashMultimap.create(); + + //TODO make this configurable + private boolean testMode = true; + + + @Activate + public void activate() { + appId = coreService.registerApplication("org.onosproject.cordfabric"); + + deviceService.addListener(deviceListener); + + if (deviceService.isAvailable(fabricDeviceId)) { + setupDefaultFlows(); + } + + log.info("Started"); + } + + @Deactivate + public void deactivate() { + deviceService.removeListener(deviceListener); + + log.info("Stopped"); + } + + private void setupDefaultFlows() { + TrafficSelector ofInBandMatchUp = DefaultTrafficSelector.builder() + .matchEthType(Ethernet.TYPE_IPV4) + .matchIPProtocol(IPv4.PROTOCOL_TCP) + .matchTcpDst(TpPort.tpPort(ofPort)) + .matchInPort(PortNumber.portNumber(6)) + .build(); + + TrafficSelector ofInBandMatchDown = DefaultTrafficSelector.builder() + .matchEthType(Ethernet.TYPE_IPV4) + .matchIPProtocol(IPv4.PROTOCOL_TCP) + .matchTcpSrc(TpPort.tpPort(ofPort)) + .matchInPort(PortNumber.portNumber(1)) + .build(); + + TrafficSelector oltMgmtUp = DefaultTrafficSelector.builder() + .matchEthSrc(MacAddress.valueOf("00:0c:d5:00:01:01")) + .matchInPort(PortNumber.portNumber(2)) + .build(); + + TrafficSelector oltMgmtDown = DefaultTrafficSelector.builder() + .matchEthDst(MacAddress.valueOf("00:0c:d5:00:01:01")) + .matchInPort(PortNumber.portNumber(9)) + .build(); + + TrafficTreatment up = DefaultTrafficTreatment.builder() + .setOutput(PortNumber.portNumber(1)) + .build(); + + TrafficTreatment down = DefaultTrafficTreatment.builder() + .setOutput(PortNumber.portNumber(6)) + .build(); + + TrafficSelector toRadius = DefaultTrafficSelector.builder() + .matchInPort(PortNumber.portNumber(2)) + .matchEthType(Ethernet.TYPE_IPV4) + .matchIPProtocol(IPv4.PROTOCOL_UDP) + .matchUdpDst(TpPort.tpPort(radiusPort)) + .build(); + + TrafficSelector fromRadius = DefaultTrafficSelector.builder() + .matchInPort(PortNumber.portNumber(5)) + .matchEthType(Ethernet.TYPE_IPV4) + .matchIPProtocol(IPv4.PROTOCOL_UDP) + .matchUdpDst(TpPort.tpPort(radiusPort)) + .build(); + + TrafficTreatment toOlt = DefaultTrafficTreatment.builder() + .setOutput(PortNumber.portNumber(2)) + .build(); + + TrafficTreatment toVolt = DefaultTrafficTreatment.builder() + .setOutput(PortNumber.portNumber(9)) + .build(); + + TrafficTreatment sentToRadius = DefaultTrafficTreatment.builder() + .setOutput(PortNumber.portNumber(5)) + .build(); + + TrafficTreatment testPort = DefaultTrafficTreatment.builder() + .setOutput(PortNumber.portNumber(8)) + .build(); + + ForwardingObjective ofTestPath = DefaultForwardingObjective.builder() + .fromApp(appId) + .makePermanent() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(TESTPRIO) + .withSelector( + DefaultTrafficSelector.builder() + .matchInPort(PortNumber.portNumber(2)) + .build()) + .withTreatment(testPort) + .add(); + + ForwardingObjective radiusToServer = DefaultForwardingObjective.builder() + .fromApp(appId) + .makePermanent() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(PRIORITY) + .withSelector(toRadius) + .withTreatment(sentToRadius) + .add(); + + ForwardingObjective serverToRadius = DefaultForwardingObjective.builder() + .fromApp(appId) + .makePermanent() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(PRIORITY) + .withSelector(fromRadius) + .withTreatment(toOlt) + .add(); + + + + ForwardingObjective upCtrl = DefaultForwardingObjective.builder() + .fromApp(appId) + .makePermanent() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(PRIORITY) + .withSelector(ofInBandMatchUp) + .withTreatment(up) + .add(); + + ForwardingObjective downCtrl = DefaultForwardingObjective.builder() + .fromApp(appId) + .makePermanent() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(PRIORITY) + .withSelector(ofInBandMatchDown) + .withTreatment(down) + .add(); + + ForwardingObjective upOltMgmt = DefaultForwardingObjective.builder() + .fromApp(appId) + .makePermanent() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(PRIORITY) + .withSelector(oltMgmtUp) + .withTreatment(toVolt) + .add(); + + ForwardingObjective downOltMgmt = DefaultForwardingObjective.builder() + .fromApp(appId) + .makePermanent() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(PRIORITY) + .withSelector(oltMgmtDown) + .withTreatment(toOlt) + .add(); + + if (testMode) { + flowObjectiveService.forward(fabricDeviceId, ofTestPath); + } + + flowObjectiveService.forward(fabricDeviceId, upCtrl); + flowObjectiveService.forward(fabricDeviceId, downCtrl); + flowObjectiveService.forward(fabricDeviceId, radiusToServer); + flowObjectiveService.forward(fabricDeviceId, serverToRadius); + flowObjectiveService.forward(fabricDeviceId, upOltMgmt); + flowObjectiveService.forward(fabricDeviceId, downOltMgmt); + } + + @Override + public void addVlan(FabricVlan vlan) { + checkNotNull(vlan); + checkArgument(vlan.ports().size() > 1); + verifyPorts(vlan.ports()); + + removeVlan(vlan.vlan()); + + if (vlan.iptv()) { + provisionIPTV(); + } + + vlan.ports().forEach(cp -> { + if (vlans.put(vlan.vlan(), cp)) { + addForwarding(vlan.vlan(), cp.deviceId(), cp.port(), + vlan.ports().stream() + .filter(p -> p != cp) + .map(ConnectPoint::port) + .collect(Collectors.toList())); + } + }); + } + + //FIXME: pass iptv vlan in here. + private void provisionIPTV() { + TrafficSelector ipTvUp = DefaultTrafficSelector.builder() + .matchVlanId(VlanId.vlanId((short) 7)) + .matchInPort(PortNumber.portNumber(2)) + .build(); + + TrafficTreatment ipTvActUp = DefaultTrafficTreatment.builder() + .setOutput(PortNumber.portNumber(7)).build(); + + TrafficSelector ipTvDown = DefaultTrafficSelector.builder() + .matchVlanId(VlanId.vlanId((short) 7)) + .matchInPort(PortNumber.portNumber(7)) + .build(); + + TrafficTreatment ipTvActDown = DefaultTrafficTreatment.builder() + .setOutput(PortNumber.portNumber(2)).build(); + + ForwardingObjective ipTvUpstream = DefaultForwardingObjective.builder() + .fromApp(appId) + .makePermanent() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(PRIORITY) + .withSelector(ipTvUp) + .withTreatment(ipTvActUp) + .add(); + + ForwardingObjective ipTvDownstream = DefaultForwardingObjective.builder() + .fromApp(appId) + .makePermanent() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(PRIORITY) + .withSelector(ipTvDown) + .withTreatment(ipTvActDown) + .add(); + + flowObjectiveService.forward(fabricDeviceId, ipTvUpstream); + flowObjectiveService.forward(fabricDeviceId, ipTvDownstream); + } + + @Override + public void removeVlan(VlanId vlanId) { + Collection<ConnectPoint> ports = vlans.removeAll(vlanId); + + ports.forEach(cp -> removeForwarding(vlanId, cp.deviceId(), cp.port(), + ports.stream() + .filter(p -> p != cp) + .map(ConnectPoint::port) + .collect(Collectors.toList()))); + } + + @Override + public List<FabricVlan> getVlans() { + List<FabricVlan> fVlans = new ArrayList<>(); + vlans.keySet().forEach(vlan -> fVlans.add( + //FIXME: Very aweful but will fo for now + new FabricVlan(vlan, vlans.get(vlan), vlan.toShort() == 201))); + return fVlans; + } + + private static void verifyPorts(List<ConnectPoint> ports) { + DeviceId deviceId = ports.get(0).deviceId(); + for (ConnectPoint connectPoint : ports) { + if (!connectPoint.deviceId().equals(deviceId)) { + throw new IllegalArgumentException("Ports must all be on the same device"); + } + } + } + + private void addForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort, + List<PortNumber> outPorts) { + + TrafficSelector selector = DefaultTrafficSelector.builder() + .matchVlanId(vlanId) + .matchInPort(inPort) + .build(); + + TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder(); + + outPorts.forEach(p -> treatmentBuilder.setOutput(p)); + + ForwardingObjective objective = DefaultForwardingObjective.builder() + .fromApp(appId) + .makePermanent() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(PRIORITY) + .withSelector(selector) + .withTreatment(treatmentBuilder.build()) + .add(new ObjectiveHandler()); + + flowObjectiveService.forward(deviceId, objective); + } + + private void removeForwarding(VlanId vlanId, DeviceId deviceId, PortNumber inPort, + List<PortNumber> outPorts) { + TrafficSelector selector = DefaultTrafficSelector.builder() + .matchVlanId(vlanId) + .matchInPort(inPort) + .build(); + + TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder(); + + outPorts.forEach(p -> treatmentBuilder.setOutput(p)); + + ForwardingObjective objective = DefaultForwardingObjective.builder() + .fromApp(appId) + .makePermanent() + .withFlag(ForwardingObjective.Flag.VERSATILE) + .withPriority(PRIORITY) + .withSelector(selector) + .withTreatment(treatmentBuilder.build()) + .remove(new ObjectiveHandler()); + + flowObjectiveService.forward(deviceId, objective); + } + + private static class ObjectiveHandler implements ObjectiveContext { + private static Logger log = LoggerFactory.getLogger(ObjectiveHandler.class); + + @Override + public void onSuccess(Objective objective) { + log.info("Flow objective operation successful: {}", objective); + } + + @Override + public void onError(Objective objective, ObjectiveError error) { + log.info("Flow objective operation failed: {}", objective); + } + } + + /** + * Internal listener for device service events. + */ + private class InternalDeviceListener implements DeviceListener { + @Override + public void event(DeviceEvent event) { + switch (event.type()) { + case DEVICE_ADDED: + case DEVICE_AVAILABILITY_CHANGED: + if (event.subject().id().equals(fabricDeviceId) && + deviceService.isAvailable(event.subject().id())) { + setupDefaultFlows(); + } + default: + break; + } + } + } +} |