2 * Copyright (c) 2014, 2015 Red Hat, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.services;
11 import java.math.BigInteger;
12 import java.net.Inet6Address;
13 import java.net.InetAddress;
14 import java.util.List;
16 import org.apache.commons.net.util.SubnetUtils;
17 import org.opendaylight.netvirt.openstack.netvirt.api.StatusCode;
18 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
19 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.Service;
20 import org.opendaylight.netvirt.openstack.netvirt.api.Action;
21 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
22 import org.opendaylight.netvirt.openstack.netvirt.api.RoutingProvider;
23 import org.opendaylight.netvirt.openstack.netvirt.providers.ConfigInterface;
24 import org.opendaylight.netvirt.openstack.netvirt.api.Status;
25 import org.opendaylight.netvirt.utils.mdsal.openflow.ActionUtils;
26 import org.opendaylight.netvirt.utils.mdsal.openflow.FlowUtils;
27 import org.opendaylight.netvirt.utils.mdsal.openflow.MatchUtils;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
42 import com.google.common.collect.Lists;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcOfEthSrcCaseBuilder;
45 import org.osgi.framework.BundleContext;
46 import org.osgi.framework.ServiceReference;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
50 public class RoutingService extends AbstractServiceInstance implements RoutingProvider, ConfigInterface {
51 private static final Logger LOG = LoggerFactory.getLogger(RoutingService.class);
52 public RoutingService() {
53 super(Service.ROUTING);
56 public RoutingService(Service service) {
61 public Status programRouterInterface(Long dpid, String sourceSegId, String destSegId, String macAddress,
62 InetAddress address, int mask, Action action) {
63 if (address instanceof Inet6Address) {
64 // WORKAROUND: For now ipv6 is not supported
65 // TODO: implement ipv6 case
66 LOG.debug("ipv6 address is not implemented yet. address {}", address);
67 return new Status(StatusCode.NOTIMPLEMENTED);
70 SubnetUtils addressSubnetInfo = new SubnetUtils(address.getHostAddress() + "/" + mask);
71 final String prefixString = addressSubnetInfo.getInfo().getNetworkAddress() + "/" + mask;
73 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid);
74 FlowBuilder flowBuilder = new FlowBuilder();
75 String flowName = "Routing_" + sourceSegId + "_" + destSegId + "_" + prefixString;
76 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(2048);
78 boolean isExternalNet = sourceSegId.equals(Constants.EXTERNAL_NETWORK);
79 MatchBuilder matchBuilder = new MatchBuilder();
81 // If matching on external network, use register reserved for InboundNatService to ensure that
82 // ip rewrite is meant to be consumed by this destination tunnel id.
83 MatchUtils.addNxRegMatch(matchBuilder,
84 new MatchUtils.RegMatch(InboundNatService.REG_FIELD, Long.valueOf(destSegId)));
86 MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(sourceSegId));
89 MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(prefixString));
90 flowBuilder.setMatch(matchBuilder.build());
92 if (action.equals(Action.ADD)) {
93 // Instructions List Stores Individual Instructions
94 InstructionsBuilder isb = new InstructionsBuilder();
95 List<Instruction> instructions = Lists.newArrayList();
96 InstructionBuilder ib = new InstructionBuilder();
97 ApplyActionsBuilder aab = new ApplyActionsBuilder();
98 ActionBuilder ab = new ActionBuilder();
99 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actionList
100 = Lists.newArrayList();
102 //if this is an east<->west route, save the src mac in case this is an ICMP echo request
104 ab.setAction(ActionUtils.nxMoveRegAction(
105 new SrcOfEthSrcCaseBuilder().setOfEthSrc(Boolean.TRUE).build(),
106 new DstNxRegCaseBuilder().setNxReg(IcmpEchoResponderService.SRC_MAC_4_HIGH_BYTES_FIELD).build(),
108 ab.setOrder(actionList.size());
109 ab.setKey(new ActionKey(actionList.size()));
110 actionList.add(ab.build());
112 ab.setAction(ActionUtils.nxMoveRegAction(
113 new SrcOfEthSrcCaseBuilder().setOfEthSrc(Boolean.TRUE).build(),
114 new DstNxRegCaseBuilder().setNxReg(IcmpEchoResponderService.SRC_MAC_2_LOW_BYTES_FIELD).build(),
116 ab.setOrder(actionList.size());
117 ab.setKey(new ActionKey(actionList.size()));
118 actionList.add(ab.build());
121 // Set source Mac address
122 ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
123 ab.setOrder(actionList.size());
124 ab.setKey(new ActionKey(actionList.size()));
125 actionList.add(ab.build());
128 ab.setAction(ActionUtils.decNwTtlAction());
129 ab.setOrder(actionList.size());
130 ab.setKey(new ActionKey(actionList.size()));
131 actionList.add(ab.build());
133 // Set Destination Tunnel ID
134 ab.setAction(ActionUtils.setTunnelIdAction(new BigInteger(destSegId)));
135 ab.setOrder(actionList.size());
136 ab.setKey(new ActionKey(actionList.size()));
137 actionList.add(ab.build());
139 // Create Apply Actions Instruction
140 aab.setAction(actionList);
141 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
143 ib.setKey(new InstructionKey(0));
144 instructions.add(ib.build());
147 ib = getMutablePipelineInstructionBuilder();
149 ib.setKey(new InstructionKey(2));
150 instructions.add(ib.build());
152 flowBuilder.setInstructions(isb.setInstruction(instructions).build());
153 writeFlow(flowBuilder, nodeBuilder);
155 removeFlow(flowBuilder, nodeBuilder);
158 // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
159 return new Status(StatusCode.SUCCESS);
163 public Status programDefaultRouteEntry(Long dpid, String segmentationId, String macAddress,
164 InetAddress nextHop, Action action) {
166 NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid);
167 FlowBuilder flowBuilder = new FlowBuilder();
168 String flowName = "DefaultRoute_" + nextHop.getHostAddress();
169 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(1024);
171 MatchBuilder matchBuilder = new MatchBuilder();
172 MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
173 flowBuilder.setMatch(matchBuilder.build());
175 if (action.equals(Action.ADD)) {
176 // Instructions List Stores Individual Instructions
177 InstructionsBuilder isb = new InstructionsBuilder();
178 List<Instruction> instructions = Lists.newArrayList();
179 InstructionBuilder ib = new InstructionBuilder();
180 ApplyActionsBuilder aab = new ApplyActionsBuilder();
181 ActionBuilder ab = new ActionBuilder();
182 List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actionList =
183 Lists.newArrayList();
185 // Set source Mac address
186 ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
188 ab.setKey(new ActionKey(0));
189 actionList.add(ab.build());
192 ab.setAction(ActionUtils.decNwTtlAction());
194 ab.setKey(new ActionKey(1));
195 actionList.add(ab.build());
197 // Create Apply Actions Instruction
198 aab.setAction(actionList);
199 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
201 ib.setKey(new InstructionKey(0));
202 instructions.add(ib.build());
205 ib = getMutablePipelineInstructionBuilder();
207 ib.setKey(new InstructionKey(1));
208 instructions.add(ib.build());
210 flowBuilder.setInstructions(isb.setInstruction(instructions).build());
212 writeFlow(flowBuilder, nodeBuilder);
214 removeFlow(flowBuilder, nodeBuilder);
217 // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
218 return new Status(StatusCode.SUCCESS);
222 public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
223 super.setDependencies(bundleContext.getServiceReference(RoutingProvider.class.getName()), this);
227 public void setDependencies(Object impl) {