blob: c5697b51d824d7f120a5c50cfb4ee27afbf459b0 [file] [log] [blame]
/*
* Copyright 2015-present 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.EthType.EtherType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
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.net.flowobjective.Objective.Operation;
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 EtherType ETH_TYPE = EtherType.ARP;
private static final int ARP_CLASSIFIER_PRIORITY = 60000;
private static final int L3_CLASSIFIER_PRIORITY = 0xffff;
private static final int L2_CLASSIFIER_PRIORITY = 50000;
private static final int USERDATA_CLASSIFIER_PRIORITY = 65535;
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_CLASSIFIER_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).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_CLASSIFIER_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());
}
});
}
@Override
public void programL3ExPortClassifierRules(DeviceId deviceId, PortNumber inPort,
IpAddress dstIp,
Objective.Operation type) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4).matchInPort(inPort)
.matchIPDst(IpPrefix.valueOf(dstIp, 32)).build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment).withSelector(selector)
.fromApp(appId).withFlag(Flag.SPECIFIC)
.withPriority(L3_CLASSIFIER_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
log.debug("L3ExToInClassifierRules-->ADD");
flowObjectiveService.forward(deviceId, objective.add());
} else {
log.debug("L3ExToInClassifierRules-->REMOVE");
flowObjectiveService.forward(deviceId, objective.remove());
}
}
@Override
public void programL3InPortClassifierRules(DeviceId deviceId, PortNumber inPort,
MacAddress srcMac, MacAddress dstMac,
SegmentationId actionVni,
Objective.Operation type) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchInPort(inPort).matchEthSrc(srcMac).matchEthDst(dstMac)
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setTunnelId(Long.parseLong(actionVni.segmentationId())).build();
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment).withSelector(selector)
.fromApp(appId).withFlag(Flag.SPECIFIC)
.withPriority(L3_CLASSIFIER_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
log.debug("L3InternalClassifierRules-->ADD");
flowObjectiveService.forward(deviceId, objective.add());
} else {
log.debug("L3InternalClassifierRules-->REMOVE");
flowObjectiveService.forward(deviceId, objective.remove());
}
}
@Override
public void programArpClassifierRules(DeviceId deviceId, IpAddress dstIp,
SegmentationId actionVni,
Objective.Operation type) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(ETH_TYPE.ethType().toShort())
.matchArpTpa(Ip4Address.valueOf(dstIp.toString()))
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setTunnelId(Long.parseLong(actionVni.segmentationId()))
.build();
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment).withSelector(selector)
.fromApp(appId).withFlag(Flag.SPECIFIC)
.withPriority(ARP_CLASSIFIER_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
log.debug("ArpClassifierRules-->ADD");
flowObjectiveService.forward(deviceId, objective.add());
} else {
log.debug("ArpClassifierRules-->REMOVE");
flowObjectiveService.forward(deviceId, objective.remove());
}
}
@Override
public void programArpClassifierRules(DeviceId deviceId, PortNumber inPort,
IpAddress dstIp,
SegmentationId actionVni,
Objective.Operation type) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchInPort(inPort).matchEthType(ETH_TYPE.ethType().toShort())
.matchArpTpa(Ip4Address.valueOf(dstIp.toString())).build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setTunnelId(Long.parseLong(actionVni.segmentationId()))
.build();
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment).withSelector(selector)
.fromApp(appId).withFlag(Flag.SPECIFIC)
.withPriority(ARP_CLASSIFIER_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
log.debug("ArpClassifierRules-->ADD");
flowObjectiveService.forward(deviceId, objective.add());
} else {
log.debug("ArpClassifierRules-->REMOVE");
flowObjectiveService.forward(deviceId, objective.remove());
}
}
@Override
public void programUserdataClassifierRules(DeviceId deviceId,
IpPrefix ipPrefix,
IpAddress dstIp,
MacAddress dstmac,
SegmentationId actionVni,
Objective.Operation type) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4).matchIPSrc(ipPrefix)
.matchIPDst(IpPrefix.valueOf(dstIp, 32)).build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setTunnelId(Long.parseLong(actionVni.segmentationId()))
.setEthDst(dstmac).build();
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment).withSelector(selector)
.fromApp(appId).withFlag(Flag.SPECIFIC)
.withPriority(USERDATA_CLASSIFIER_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
log.debug("UserdataClassifierRules-->ADD");
flowObjectiveService.forward(deviceId, objective.add());
} else {
log.debug("UserdataClassifierRules-->REMOVE");
flowObjectiveService.forward(deviceId, objective.remove());
}
}
@Override
public void programExportPortArpClassifierRules(Port exportPort,
DeviceId deviceId,
Operation type) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(EtherType.ARP.ethType().toShort())
.matchInPort(exportPort.number()).build();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
treatment.add(Instructions.createOutput(PortNumber.CONTROLLER));
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment.build())
.withSelector(selector).fromApp(appId).withFlag(Flag.SPECIFIC)
.withPriority(L3_CLASSIFIER_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
flowObjectiveService.forward(deviceId, objective.add());
} else {
flowObjectiveService.forward(deviceId, objective.remove());
}
}
}