/* * 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.Inet6Address; import java.net.InetAddress; import java.util.List; import org.apache.commons.net.util.SubnetUtils; import org.opendaylight.ovsdb.openstack.netvirt.api.Action; import org.opendaylight.ovsdb.openstack.netvirt.api.Constants; import org.opendaylight.ovsdb.openstack.netvirt.api.RoutingProvider; 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.OF13Provider; import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service; import org.opendaylight.ovsdb.openstack.netvirt.api.Status; import org.opendaylight.ovsdb.openstack.netvirt.api.StatusCode; import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils; 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.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; 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.instruction.ApplyActionsCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder; 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.Node; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; import com.google.common.collect.Lists; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RoutingService extends AbstractServiceInstance implements RoutingProvider, ConfigInterface { private static final Logger LOG = LoggerFactory.getLogger(RoutingService.class); public RoutingService() { super(Service.ROUTING); } public RoutingService(Service service) { super(service); } @Override public Status programRouterInterface(Long dpid, String sourceSegId, String destSegId, String macAddress, InetAddress address, int mask, Action action) { String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid; MatchBuilder matchBuilder = new MatchBuilder(); NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName); // Instructions List Stores Individual Instructions InstructionsBuilder isb = new InstructionsBuilder(); List instructions = Lists.newArrayList(); InstructionBuilder ib = new InstructionBuilder(); ApplyActionsBuilder aab = new ApplyActionsBuilder(); ActionBuilder ab = new ActionBuilder(); List actionList = Lists.newArrayList(); if (sourceSegId.equals(Constants.EXTERNAL_NETWORK)) { // If matching on external network, use register reserved for InboundNatService to ensure that // ip rewrite is meant to be consumed by this destination tunnel id. MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(InboundNatService.REG_FIELD, Long.valueOf(destSegId))); } else { MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(sourceSegId)); } if (address instanceof Inet6Address) { // WORKAROUND: For now ipv6 is not supported // TODO: implement ipv6 case LOG.debug("ipv6 address is not implemented yet. address {}", address); return new Status(StatusCode.NOTIMPLEMENTED); } SubnetUtils addressSubnetInfo = new SubnetUtils(address.getHostAddress() + "/" + mask); final String prefixString = addressSubnetInfo.getInfo().getNetworkAddress() + "/" + mask; MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(prefixString)); // Set source Mac address ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress))); ab.setOrder(0); ab.setKey(new ActionKey(0)); actionList.add(ab.build()); // DecTTL ab.setAction(ActionUtils.decNwTtlAction()); ab.setOrder(1); ab.setKey(new ActionKey(1)); actionList.add(ab.build()); // Set Destination Tunnel ID ab.setAction(ActionUtils.setTunnelIdAction(new BigInteger(destSegId))); ab.setOrder(2); ab.setKey(new ActionKey(2)); actionList.add(ab.build()); // Create Apply Actions Instruction aab.setAction(actionList); ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); ib.setOrder(0); ib.setKey(new InstructionKey(0)); instructions.add(ib.build()); // Goto Next Table ib = getMutablePipelineInstructionBuilder(); ib.setOrder(2); ib.setKey(new InstructionKey(2)); instructions.add(ib.build()); FlowBuilder flowBuilder = new FlowBuilder(); flowBuilder.setMatch(matchBuilder.build()); flowBuilder.setInstructions(isb.setInstruction(instructions).build()); String flowId = "Routing_" + sourceSegId + "_" + destSegId + "_" + prefixString; flowBuilder.setId(new FlowId(flowId)); FlowKey key = new FlowKey(new FlowId(flowId)); flowBuilder.setBarrier(true); flowBuilder.setTableId(this.getTable()); flowBuilder.setKey(key); flowBuilder.setPriority(2048); flowBuilder.setFlowName(flowId); flowBuilder.setHardTimeout(0); flowBuilder.setIdleTimeout(0); if (action.equals(Action.ADD)) { 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 programDefaultRouteEntry(Long dpid, String segmentationId, String macAddress, InetAddress nextHop, Action action) { String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid; MatchBuilder matchBuilder = new MatchBuilder(); NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName); MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)); // Instructions List Stores Individual Instructions InstructionsBuilder isb = new InstructionsBuilder(); List instructions = Lists.newArrayList(); InstructionBuilder ib = new InstructionBuilder(); ApplyActionsBuilder aab = new ApplyActionsBuilder(); ActionBuilder ab = new ActionBuilder(); List actionList = Lists.newArrayList(); // Set source Mac address ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress))); ab.setOrder(0); ab.setKey(new ActionKey(0)); actionList.add(ab.build()); // DecTTL ab.setAction(ActionUtils.decNwTtlAction()); ab.setOrder(1); ab.setKey(new ActionKey(1)); actionList.add(ab.build()); // Create Apply Actions Instruction aab.setAction(actionList); ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); 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 flowBuilder = new FlowBuilder(); flowBuilder.setMatch(matchBuilder.build()); flowBuilder.setInstructions(isb.setInstruction(instructions).build()); String flowId = "DefaultRoute_" + nextHop.getHostAddress(); flowBuilder.setId(new FlowId(flowId)); FlowKey key = new FlowKey(new FlowId(flowId)); flowBuilder.setBarrier(true); flowBuilder.setTableId(this.getTable()); flowBuilder.setKey(key); flowBuilder.setPriority(1024); flowBuilder.setFlowName(flowId); flowBuilder.setHardTimeout(0); flowBuilder.setIdleTimeout(0); if (action.equals(Action.ADD)) { 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(RoutingProvider.class.getName()), this); } @Override public void setDependencies(Object impl) { } }