All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.onosproject.provider.of.group.impl.GroupModBuilder Maven / Gradle / Ivy

There is a newer version: 1.6.0
Show newest version
/*
 * 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.provider.of.group.impl;

import static org.slf4j.LoggerFactory.getLogger;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onosproject.core.GroupId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.driver.DefaultDriverData;
import org.onosproject.net.driver.DefaultDriverHandler;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.openflow.controller.ExtensionTreatmentInterpreter;
import org.projectfloodlight.openflow.protocol.OFBucket;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFGroupAdd;
import org.projectfloodlight.openflow.protocol.OFGroupDelete;
import org.projectfloodlight.openflow.protocol.OFGroupMod;
import org.projectfloodlight.openflow.protocol.OFGroupType;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
import org.projectfloodlight.openflow.types.CircuitSignalID;
import org.projectfloodlight.openflow.types.EthType;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.IPv6Address;
import org.projectfloodlight.openflow.types.IPv6FlowLabel;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFBooleanValue;
import org.projectfloodlight.openflow.types.OFGroup;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.types.U64;
import org.projectfloodlight.openflow.types.VlanPcp;
import org.slf4j.Logger;

/*
 * Builder for GroupMod.
 */
public final class GroupModBuilder {

    private GroupBuckets buckets;
    private GroupId groupId;
    private GroupDescription.Type type;
    private OFFactory factory;
    private Long xid;
    private Optional driverService;

    private final Logger log = getLogger(getClass());

    private static final int OFPCML_NO_BUFFER = 0xffff;

    private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
                             GroupDescription.Type type, OFFactory factory,
                             Optional xid) {
        this.buckets = buckets;
        this.groupId = groupId;
        this.type = type;
        this.factory = factory;
        this.xid = xid.orElse((long) 0);
    }

    private GroupModBuilder(GroupBuckets buckets, GroupId groupId,
                            GroupDescription.Type type, OFFactory factory,
                            Optional xid, Optional driverService) {
       this.buckets = buckets;
       this.groupId = groupId;
       this.type = type;
       this.factory = factory;
       this.xid = xid.orElse((long) 0);
       this.driverService = driverService;
   }
    /**
     * Creates a builder for GroupMod.
     *
     * @param buckets GroupBuckets object
     * @param groupId Group Id to create
     * @param type Group type
     * @param factory OFFactory object
     * @param xid transaction ID
     * @return GroupModBuilder object
     */
    public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
                                          GroupDescription.Type type, OFFactory factory,
                                          Optional xid) {

        return new GroupModBuilder(buckets, groupId, type, factory, xid);
    }

    /**
     * Creates a builder for GroupMod.
     *
     * @param buckets GroupBuckets object
     * @param groupId Group Id to create
     * @param type Group type
     * @param factory OFFactory object
     * @param xid transaction ID
     * @param driverService driver Service
     * @return GroupModBuilder object
     */
    public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId,
                                          GroupDescription.Type type, OFFactory factory,
                                          Optional xid, Optional driverService) {

        return new GroupModBuilder(buckets, groupId, type, factory, xid, driverService);
    }

    /**
     * Builds the GroupAdd OF message.
     *
     * @return GroupAdd OF message
     */
    public OFGroupAdd buildGroupAdd() {

        List ofBuckets = new ArrayList();
        for (GroupBucket bucket: buckets.buckets()) {
            List actions = buildActions(bucket.treatment());

            OFBucket.Builder bucketBuilder = factory.buildBucket();
            bucketBuilder.setActions(actions);
            if (type == GroupDescription.Type.SELECT) {
                bucketBuilder.setWeight(1);
            }

            if (type == GroupDescription.Type.FAILOVER && bucket.watchPort() != null) {
                bucketBuilder.setWatchPort(OFPort.of((int) bucket.watchPort().toLong()));
            } else {
                bucketBuilder.setWatchPort(OFPort.ANY);
            }
            if (type == GroupDescription.Type.FAILOVER &&  bucket.watchGroup() != null) {
                bucketBuilder.setWatchGroup(OFGroup.of(bucket.watchGroup().id()));
            } else {
                bucketBuilder.setWatchGroup(OFGroup.ANY);
            }
            OFBucket ofBucket = bucketBuilder.build();
            ofBuckets.add(ofBucket);
        }

        OFGroupAdd groupMsg = factory.buildGroupAdd()
                .setGroup(OFGroup.of(groupId.id()))
                .setBuckets(ofBuckets)
                .setGroupType(getOFGroupType(type))
                .setXid(xid)
                .build();

        return groupMsg;
    }

    /**
     * Builds the GroupMod OF message.
     *
     * @return GroupMod OF message
     */
    public OFGroupMod buildGroupMod() {
        List ofBuckets = new ArrayList();
        for (GroupBucket bucket: buckets.buckets()) {
            List actions = buildActions(bucket.treatment());

            OFBucket.Builder bucketBuilder = factory.buildBucket();
            bucketBuilder.setActions(actions);
            if (type == GroupDescription.Type.SELECT) {
                bucketBuilder.setWeight(1);
            }
            bucketBuilder.setWatchGroup(OFGroup.ANY);
            bucketBuilder.setWatchPort(OFPort.ANY);
            OFBucket ofBucket = bucketBuilder.build();
            ofBuckets.add(ofBucket);
        }

        OFGroupMod groupMsg = factory.buildGroupModify()
                .setGroup(OFGroup.of(groupId.id()))
                .setBuckets(ofBuckets)
                .setGroupType(getOFGroupType(type))
                .setXid(xid)
                .build();

        return groupMsg;
    }

    /**
     * Builds the GroupDel OF message.
     *
     * @return GroupDel OF message
     */
    public OFGroupDelete buildGroupDel() {

        OFGroupDelete groupMsg = factory.buildGroupDelete()
                .setGroup(OFGroup.of(groupId.id()))
                .setGroupType(OFGroupType.SELECT)
                .setXid(xid)
                .build();

        return groupMsg;
    }

    private List buildActions(TrafficTreatment treatment) {
        if (treatment == null) {
            return Collections.emptyList();
        }

        List actions = new LinkedList<>();
        for (Instruction i : treatment.allInstructions()) {
            switch (i.type()) {
                case DROP:
                    log.warn("Saw drop action; assigning drop action");
                    return Collections.emptyList();
                case L0MODIFICATION:
                    actions.add(buildL0Modification(i));
                    break;
                case L2MODIFICATION:
                    actions.add(buildL2Modification(i));
                    break;
                case L3MODIFICATION:
                    actions.add(buildL3Modification(i));
                    break;
                case OUTPUT:
                    Instructions.OutputInstruction out =
                            (Instructions.OutputInstruction) i;
                    OFActionOutput.Builder action = factory.actions().buildOutput()
                            .setPort(OFPort.of((int) out.port().toLong()));
                    if (out.port().equals(PortNumber.CONTROLLER)) {
                        action.setMaxLen(OFPCML_NO_BUFFER);
                    }
                    actions.add(action.build());
                    break;
                case GROUP:
                    Instructions.GroupInstruction grp =
                            (Instructions.GroupInstruction) i;
                    OFActionGroup.Builder actgrp = factory.actions().buildGroup()
                            .setGroup(OFGroup.of(grp.groupId().id()));
                    actions.add(actgrp.build());
                    break;
                case EXTENSION:
                    Instructions.ExtensionInstructionWrapper wrapper =
                    (Instructions.ExtensionInstructionWrapper) i;
                    actions.add(buildExtensionAction(
                            wrapper.extensionInstruction(), wrapper.deviceId()));
                    break;
                default:
                    log.warn("Instruction type {} not yet implemented.", i.type());
            }
        }

        return actions;
    }

    private OFAction buildL0Modification(Instruction i) {
        L0ModificationInstruction l0m = (L0ModificationInstruction) i;
        switch (l0m.subtype()) {
            case LAMBDA:
                L0ModificationInstruction.ModLambdaInstruction ml =
                        (L0ModificationInstruction.ModLambdaInstruction) i;
                return factory.actions().circuit(factory.oxms().ochSigidBasic(
                        new CircuitSignalID((byte) 1, (byte) 2, ml.lambda(), (short) 1)));
            default:
                log.warn("Unimplemented action type {}.", l0m.subtype());
                break;
        }
        return null;
    }

    private OFAction buildL2Modification(Instruction i) {
        L2ModificationInstruction l2m = (L2ModificationInstruction) i;
        L2ModificationInstruction.ModEtherInstruction eth;
        OFOxm oxm = null;
        switch (l2m.subtype()) {
            case ETH_DST:
                eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
                oxm = factory.oxms().ethDst(MacAddress.of(eth.mac().toLong()));
                break;
            case ETH_SRC:
                eth = (L2ModificationInstruction.ModEtherInstruction) l2m;
                oxm = factory.oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
                break;
            case VLAN_ID:
                L2ModificationInstruction.ModVlanIdInstruction vlanId =
                        (L2ModificationInstruction.ModVlanIdInstruction) l2m;
                oxm = factory.oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
                break;
            case VLAN_PCP:
                L2ModificationInstruction.ModVlanPcpInstruction vlanPcp =
                        (L2ModificationInstruction.ModVlanPcpInstruction) l2m;
                oxm = factory.oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
                break;
            case VLAN_POP:
                return factory.actions().popVlan();
            case VLAN_PUSH:
                L2ModificationInstruction.PushHeaderInstructions pushVlanInstruction
                        = (L2ModificationInstruction.PushHeaderInstructions) l2m;
                return factory.actions().pushVlan(
                        EthType.of(pushVlanInstruction.ethernetType().toShort()));
            case MPLS_PUSH:
                L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
                        (L2ModificationInstruction.PushHeaderInstructions) l2m;
                return factory.actions().pushMpls(EthType.of(pushHeaderInstructions
                                                             .ethernetType().toShort()));
            case MPLS_POP:
                L2ModificationInstruction.PushHeaderInstructions popHeaderInstructions =
                        (L2ModificationInstruction.PushHeaderInstructions) l2m;
                return factory.actions().popMpls(EthType.of(popHeaderInstructions
                                                            .ethernetType().toShort()));
            case MPLS_LABEL:
                L2ModificationInstruction.ModMplsLabelInstruction mplsLabel =
                        (L2ModificationInstruction.ModMplsLabelInstruction) l2m;
                oxm = factory.oxms().mplsLabel(U32.of(mplsLabel.label().toInt()));
                break;
            case MPLS_BOS:
                L2ModificationInstruction.ModMplsBosInstruction mplsBos =
                        (L2ModificationInstruction.ModMplsBosInstruction) l2m;
                oxm = factory.oxms()
                        .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE
                                                   : OFBooleanValue.FALSE);
                break;
            case DEC_MPLS_TTL:
                return factory.actions().decMplsTtl();
            case TUNNEL_ID:
                L2ModificationInstruction.ModTunnelIdInstruction tunnelId =
                        (L2ModificationInstruction.ModTunnelIdInstruction) l2m;
                oxm = factory.oxms().tunnelId(U64.of(tunnelId.tunnelId()));
                break;
            default:
                log.warn("Unimplemented action type {}.", l2m.subtype());
                break;
        }

        if (oxm != null) {
            return factory.actions().buildSetField().setField(oxm).build();
        }
        return null;
    }

    private OFAction buildL3Modification(Instruction i) {
        L3ModificationInstruction l3m = (L3ModificationInstruction) i;
        L3ModificationInstruction.ModIPInstruction ip;
        Ip4Address ip4;
        Ip6Address ip6;
        OFOxm oxm = null;
        switch (l3m.subtype()) {
            case IPV4_SRC:
                ip = (L3ModificationInstruction.ModIPInstruction) i;
                ip4 = ip.ip().getIp4Address();
                oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
                break;
            case IPV4_DST:
                ip = (L3ModificationInstruction.ModIPInstruction) i;
                ip4 = ip.ip().getIp4Address();
                oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
                break;
            case IPV6_SRC:
                ip = (L3ModificationInstruction.ModIPInstruction) i;
                ip6 = ip.ip().getIp6Address();
                oxm = factory.oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
                break;
            case IPV6_DST:
                ip = (L3ModificationInstruction.ModIPInstruction) i;
                ip6 = ip.ip().getIp6Address();
                oxm = factory.oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
                break;
            case IPV6_FLABEL:
                L3ModificationInstruction.ModIPv6FlowLabelInstruction flowLabelInstruction =
                    (L3ModificationInstruction.ModIPv6FlowLabelInstruction) i;
                int flowLabel = flowLabelInstruction.flowLabel();
                oxm = factory.oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
                break;
            case DEC_TTL:
                return factory.actions().decNwTtl();
            case TTL_IN:
                return factory.actions().copyTtlIn();
            case TTL_OUT:
                return factory.actions().copyTtlOut();
            default:
                log.warn("Unimplemented action type {}.", l3m.subtype());
                break;
        }

        if (oxm != null) {
            return factory.actions().buildSetField().setField(oxm).build();
        }
        return null;
    }

    private OFGroupType getOFGroupType(GroupDescription.Type groupType) {
        switch (groupType) {
            case INDIRECT:
                return OFGroupType.INDIRECT;
            case SELECT:
                return OFGroupType.SELECT;
            case FAILOVER:
                return OFGroupType.FF;
            case ALL:
                return OFGroupType.ALL;
            default:
                log.error("Unsupported group type : {}", groupType);
                break;
        }
        return null;
    }

    private OFAction buildExtensionAction(ExtensionTreatment i, DeviceId deviceId) {
        if (!driverService.isPresent()) {
            log.error("No driver service present");
            return null;
        }
        Driver driver = driverService.get().getDriver(deviceId);
        if (driver.hasBehaviour(ExtensionTreatmentInterpreter.class)) {
            DefaultDriverHandler handler =
                    new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
            ExtensionTreatmentInterpreter interpreter = handler.behaviour(ExtensionTreatmentInterpreter.class);
            return interpreter.mapInstruction(factory, i);
        }

        return null;
    }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy