/* * Copyright (c) 2014, 2015 Red Hat, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services; import java.math.BigInteger; import java.net.InetAddress; import java.net.Inet6Address; import java.net.UnknownHostException; import java.util.List; import org.opendaylight.ovsdb.openstack.netvirt.api.Action; import org.opendaylight.ovsdb.openstack.netvirt.api.InboundNatProvider; import org.opendaylight.ovsdb.openstack.netvirt.api.Status; import org.opendaylight.ovsdb.openstack.netvirt.api.StatusCode; import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface; import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance; import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service; import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils; import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils; import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils; import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; import com.google.common.collect.Lists; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class InboundNatService extends AbstractServiceInstance implements ConfigInterface, InboundNatProvider { private static final Logger LOG = LoggerFactory.getLogger(InboundNatService.class); public static final Class REG_FIELD = NxmNxReg3.class; public InboundNatService() { super(Service.INBOUND_NAT); } public InboundNatService(Service service) { super(service); } @Override public Status programIpRewriteRule(Long dpid, Long inPort, String destSegId, InetAddress matchAddress, InetAddress rewriteAddress, Action action) { NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid); FlowBuilder flowBuilder = new FlowBuilder(); String flowName = "InboundNAT_" + inPort + "_" + destSegId + "_" + matchAddress.getHostAddress(); FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(1024); MatchBuilder matchBuilder = new MatchBuilder(); MatchUtils.createInPortMatch(matchBuilder, dpid, inPort); MatchUtils.createDstL3IPv4Match(matchBuilder, MatchUtils.iPv4PrefixFromIPv4Address(matchAddress.getHostAddress())); flowBuilder.setMatch(matchBuilder.build()); if (action.equals(Action.ADD)) { // Instructions List Stores Individual Instructions InstructionsBuilder isb = new InstructionsBuilder(); List instructions = Lists.newArrayList(); InstructionBuilder ib = new InstructionBuilder(); // Set register to indicate that rewrite took place ActionBuilder actionBuilder = new ActionBuilder(); actionBuilder.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(REG_FIELD).build(), new BigInteger(destSegId))); // Set Dest IP address and set REG_FIELD InstructionUtils.createNwDstInstructions(ib, MatchUtils.iPv4PrefixFromIPv4Address(rewriteAddress.getHostAddress()), actionBuilder); ib.setOrder(0); ib.setKey(new InstructionKey(0)); instructions.add(ib.build()); // Goto Next Table ib = getMutablePipelineInstructionBuilder(); ib.setOrder(1); ib.setKey(new InstructionKey(1)); instructions.add(ib.build()); flowBuilder.setInstructions(isb.setInstruction(instructions).build()); writeFlow(flowBuilder, nodeBuilder); } else { removeFlow(flowBuilder, nodeBuilder); } // ToDo: WriteFlow/RemoveFlow should return something we can use to check success return new Status(StatusCode.SUCCESS); } @Override public Status programIpRewriteExclusion(Long dpid, String segmentationId, String excludedCidr, Action action) { String ipAddress = excludedCidr.substring(0, excludedCidr.indexOf("/")); InetAddress inetAddress; try { inetAddress = InetAddress.getByName(ipAddress); } catch (UnknownHostException e) { return new Status(StatusCode.BADREQUEST); } if (inetAddress instanceof Inet6Address) { // WORKAROUND: For now ipv6 is not supported // TODO: implement ipv6 cidr case LOG.debug("ipv6 cidr is not implemented yet. cidr {}", excludedCidr); return new Status(StatusCode.NOTIMPLEMENTED); } NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid); FlowBuilder flowBuilder = new FlowBuilder(); String flowName = "InboundNATExclusion_" + segmentationId + "_" + excludedCidr; FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(1024); MatchBuilder matchBuilder = new MatchBuilder(); MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)); MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(excludedCidr)); flowBuilder.setMatch(matchBuilder.build()); if (action.equals(Action.ADD)) { // Instructions List Stores Individual Instructions InstructionsBuilder isb = new InstructionsBuilder(); List instructions = Lists.newArrayList(); InstructionBuilder ib; // Goto Next Table ib = getMutablePipelineInstructionBuilder(); ib.setOrder(0); ib.setKey(new InstructionKey(0)); instructions.add(ib.build()); flowBuilder.setInstructions(isb.setInstruction(instructions).build()); writeFlow(flowBuilder, nodeBuilder); } else { removeFlow(flowBuilder, nodeBuilder); } // ToDo: WriteFlow/RemoveFlow should return something we can use to check success return new Status(StatusCode.SUCCESS); } @Override public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) { super.setDependencies(bundleContext.getServiceReference(InboundNatProvider.class.getName()), this); } @Override public void setDependencies(Object impl) {} }