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

org.onosproject.openstacknetworking.switching.OpenstackSecurityGroupRulePopulator Maven / Gradle / Ivy

There is a newer version: 1.6.0
Show newest version
/*
* Copyright 2016 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.openstacknetworking.switching;

import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.TpPort;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
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.openstackinterface.OpenstackInterfaceService;
import org.onosproject.openstackinterface.OpenstackSecurityGroup;
import org.onosproject.openstackinterface.OpenstackSecurityGroupRule;
import org.onosproject.openstacknetworking.OpenstackPortInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * Populates flows rules for Security Groups of VMs.
 *
 */
public class OpenstackSecurityGroupRulePopulator {

    private static Logger log = LoggerFactory
            .getLogger(OpenstackSecurityGroupRulePopulator.class);

    private OpenstackInterfaceService openstackService;
    private FlowObjectiveService flowObjectiveService;

    private ApplicationId appId;

    private static final String PROTO_ICMP = "ICMP";
    private static final String PROTO_TCP = "TCP";
    private static final String PROTO_UDP = "UDP";

    private static final String ETHTYPE_IPV4 = "IPV4";

    private static final IpPrefix IP_PREFIX_ANY = Ip4Prefix.valueOf("0.0.0.0/0");

    private static final int ACL_RULE_PRIORITY = 30000;

    /**
     * Constructor.
     *
     * @param appId application ID
     * @param openstackService OpenStack interface service
     * @param flowObjectiveService flow objective service
     */
    public OpenstackSecurityGroupRulePopulator(ApplicationId appId, OpenstackInterfaceService openstackService,
                                               FlowObjectiveService flowObjectiveService) {
        this.appId = appId;
        this.openstackService = openstackService;
        this.flowObjectiveService = flowObjectiveService;
    }

    /**
     * Populates flow rules for security groups.
     *
     * @param id Device ID
     * @param sgId Security Group ID
     * @param vmIp VM IP address
     * @param portInfoMap Port Info map
     */
    public void populateSecurityGroupRules(DeviceId id, String sgId, Ip4Address vmIp,
                                           Map portInfoMap) {
        OpenstackSecurityGroup securityGroup = openstackService.getSecurityGroup(sgId);
        if (securityGroup != null) {
            securityGroup.rules().stream().forEach(sgRule -> {
                if (sgRule.remoteGroupId() != null && !sgRule.remoteGroupId().equals("null")) {
                    openstackService.ports().stream()
                        .filter(port -> port.securityGroups().contains(sgRule.remoteGroupId()))
                        .flatMap(port -> port.fixedIps().values().stream())
                        .forEach(remoteIp -> setSecurityGroupRule(id, sgRule,
                                vmIp, IpPrefix.valueOf((IpAddress) remoteIp, 32)));
                } else {
                    setSecurityGroupRule(id, sgRule, vmIp, sgRule.remoteIpPrefix());
                }
            });

            openstackService.ports().stream().forEach(osPort ->
                osPort.securityGroups().stream().forEach(remoteVmSgId -> {
                    OpenstackSecurityGroup remoteVmSg = openstackService.getSecurityGroup(remoteVmSgId);
                    remoteVmSg.rules().stream()
                        .filter(remoteVmSgRule -> remoteVmSgRule.remoteGroupId().equals(sgId))
                        .forEach(remoteVmSgRule -> {
                            Ip4Address remoteVmIp =
                                    (Ip4Address) osPort.fixedIps().values().stream().findAny().orElse(null);
                            OpenstackPortInfo osPortInfo = portInfoMap.get(OpenstackSwitchingManager.PORTNAME_PREFIX_VM
                                    + osPort.id().substring(0, 11));
                            if (osPortInfo != null && remoteVmIp != null) {
                                setSecurityGroupRule(osPortInfo.deviceId(), remoteVmSgRule, remoteVmIp,
                                        IpPrefix.valueOf(vmIp, 32));
                            }
                        });
                }));
        }
    }

    /**
     * Removes flow rules for security groups.
     *
     * @param id Device ID
     * @param sgId Security Group ID to remove
     * @param vmIp VM IP address
     * @param portInfoMap port info map
     * @param securityGroupMap security group info map
     */
    public void removeSecurityGroupRules(DeviceId id, String sgId, Ip4Address vmIp,
                                         Map portInfoMap,
                                         Map securityGroupMap) {
        OpenstackSecurityGroup securityGroup = securityGroupMap.get(sgId);
        if (securityGroup != null) {
            securityGroup.rules().stream().forEach(sgRule -> {
                if (sgRule.remoteGroupId() != null && !sgRule.remoteGroupId().equals("null")) {
                    portInfoMap.values().stream()
                            .filter(portInfo -> portInfo.securityGroups().contains(sgRule.remoteGroupId()))
                            .map(OpenstackPortInfo::ip)
                            .forEach(remoteIp -> {
                                removeSecurityGroupRule(id, sgRule, vmIp, IpPrefix.valueOf(remoteIp, 32));
                            });
                } else {
                    removeSecurityGroupRule(id, sgRule, vmIp, sgRule.remoteIpPrefix());
                }
            });

            portInfoMap.values().stream()
                .forEach(portInfo -> portInfo.securityGroups()
                    .forEach(remoteVmSgId -> {
                        OpenstackSecurityGroup remoteVmSg = securityGroupMap.get(remoteVmSgId);
                        remoteVmSg.rules().stream()
                            .filter(remoteVmSgRule -> remoteVmSgRule.remoteGroupId().equals(sgId))
                            .forEach(remoteVmSgRule -> removeSecurityGroupRule(portInfo.deviceId(),
                                    remoteVmSgRule, portInfo.ip(), IpPrefix.valueOf(vmIp, 32)));
                    }));
        }
    }

    private void setSecurityGroupRule(DeviceId id, OpenstackSecurityGroupRule sgRule,
                                      Ip4Address vmIp, IpPrefix remoteIp) {
        ForwardingObjective.Builder foBuilder = buildFlowObjective(id, sgRule, vmIp, remoteIp);
        if (foBuilder != null) {
            flowObjectiveService.forward(id, foBuilder.add());
        }
    }

    private void removeSecurityGroupRule(DeviceId id, OpenstackSecurityGroupRule sgRule,
                                      Ip4Address vmIp, IpPrefix remoteIp) {
        ForwardingObjective.Builder foBuilder = buildFlowObjective(id, sgRule, vmIp, remoteIp);
        if (foBuilder != null) {
            flowObjectiveService.forward(id, foBuilder.remove());
        }
    }

    ForwardingObjective.Builder buildFlowObjective(DeviceId id, OpenstackSecurityGroupRule sgRule,
                                           Ip4Address vmIp, IpPrefix remoteIp) {
        if (remoteIp != null && remoteIp.equals(IpPrefix.valueOf(vmIp, 32))) {
            return null;
        }
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        buildMatchs(sBuilder, sgRule, vmIp, remoteIp);

        ForwardingObjective.Builder foBuilder = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(tBuilder.build())
                .withPriority(ACL_RULE_PRIORITY)
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .fromApp(appId);

        return foBuilder;
    }

    private void buildMatchs(TrafficSelector.Builder sBuilder, OpenstackSecurityGroupRule sgRule,
                             Ip4Address vmIp, IpPrefix remoteIp) {
        buildMatchEthType(sBuilder, sgRule.ethertype());
        buildMatchDirection(sBuilder, sgRule.direction(), vmIp);
        buildMatchProto(sBuilder, sgRule.protocol());
        buildMatchPort(sBuilder, sgRule.protocol(), sgRule.direction(), sgRule.portRangeMax(), sgRule.portRangeMin());
        buildMatchRemoteIp(sBuilder, remoteIp, sgRule.direction());
    }

    private void buildMatchDirection(TrafficSelector.Builder sBuilder,
                                     OpenstackSecurityGroupRule.Direction direction, Ip4Address vmIp) {
        if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
            sBuilder.matchIPSrc(IpPrefix.valueOf(vmIp, 32));
        } else {
            sBuilder.matchIPDst(IpPrefix.valueOf(vmIp, 32));
        }
    }

    private void buildMatchEthType(TrafficSelector.Builder sBuilder, String ethertype) {
        // Either IpSrc or IpDst (or both) is set by default, and we need to set EthType as IPv4.
        sBuilder.matchEthType(Ethernet.TYPE_IPV4);
        if (ethertype != null && ethertype != "null" &&
                !ethertype.toUpperCase().equals(ETHTYPE_IPV4)) {
            log.error("EthType {} is not supported yet in Security Group", ethertype);
        }
    }

    private void buildMatchRemoteIp(TrafficSelector.Builder sBuilder, IpPrefix remoteIpPrefix,
                                                       OpenstackSecurityGroupRule.Direction direction) {
        if (remoteIpPrefix != null && !remoteIpPrefix.getIp4Prefix().equals(IP_PREFIX_ANY)) {
            if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
                sBuilder.matchIPDst(remoteIpPrefix);
            } else {
                sBuilder.matchIPSrc(remoteIpPrefix);
            }
        }
    }

    private void buildMatchProto(TrafficSelector.Builder sBuilder, String protocol) {
        if (protocol != null) {
            switch (protocol.toUpperCase()) {
                case PROTO_ICMP:
                    sBuilder.matchIPProtocol(IPv4.PROTOCOL_ICMP);
                    break;
                case PROTO_TCP:
                    sBuilder.matchIPProtocol(IPv4.PROTOCOL_TCP);
                    break;
                case PROTO_UDP:
                    sBuilder.matchIPProtocol(IPv4.PROTOCOL_UDP);
                    break;
                default:
            }
        }
    }

    private void buildMatchPort(TrafficSelector.Builder sBuilder, String protocol,
                                                   OpenstackSecurityGroupRule.Direction direction,
                                                   int portMin, int portMax) {
        if (portMin > 0 && portMax > 0 && portMin == portMax) {
            if (protocol.toUpperCase().equals(PROTO_TCP)) {
                if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
                    sBuilder.matchTcpDst(TpPort.tpPort(portMax));
                } else {
                    sBuilder.matchTcpSrc(TpPort.tpPort(portMax));
                }
            } else if (protocol.toUpperCase().equals(PROTO_UDP)) {
                if (direction.equals(OpenstackSecurityGroupRule.Direction.EGRESS)) {
                    sBuilder.matchUdpDst(TpPort.tpPort(portMax));
                } else {
                    sBuilder.matchUdpSrc(TpPort.tpPort(portMax));
                }
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy