Fix for BUG 4067 (LBaaS flows don't get installed in the switch.)
[ovsdb.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / openflow13 / services / RoutingService.java
1 /*
2  * Copyright (c) 2014, 2015 Red Hat, Inc. and others. All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
10
11 import java.math.BigInteger;
12 import java.net.Inet6Address;
13 import java.net.InetAddress;
14 import java.util.List;
15
16 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.RoutingProvider;
19 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
20 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
21 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.OF13Provider;
22 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
23 import org.opendaylight.ovsdb.openstack.netvirt.api.Status;
24 import org.opendaylight.ovsdb.openstack.netvirt.api.StatusCode;
25 import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
26 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
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.inventory.rev130819.tables.table.FlowKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
41 //import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
43
44 import com.google.common.collect.Lists;
45 import org.osgi.framework.BundleContext;
46 import org.osgi.framework.ServiceReference;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
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);
54     }
55
56     public RoutingService(Service service) {
57         super(service);
58     }
59
60     @Override
61     public Status programRouterInterface(Long dpid, String sourceSegId, String destSegId, String macAddress,
62                                          InetAddress address, int mask, Action action) {
63
64         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
65
66         MatchBuilder matchBuilder = new MatchBuilder();
67         NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName);
68
69         // Instructions List Stores Individual Instructions
70         InstructionsBuilder isb = new InstructionsBuilder();
71         List<Instruction> instructions = Lists.newArrayList();
72         InstructionBuilder ib = new InstructionBuilder();
73         ApplyActionsBuilder aab = new ApplyActionsBuilder();
74         ActionBuilder ab = new ActionBuilder();
75         List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actionList = Lists.newArrayList();
76
77         if (sourceSegId.equals(Constants.EXTERNAL_NETWORK)) {
78             // If matching on external network, use register reserved for InboundNatService to ensure that
79             // ip rewrite is meant to be consumed by this destination tunnel id.
80             MatchUtils.addNxRegMatch(matchBuilder,
81                     new MatchUtils.RegMatch(InboundNatService.REG_FIELD, Long.valueOf(destSegId)));
82         } else {
83             MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(sourceSegId));
84         }
85
86         if (address instanceof Inet6Address) {
87             // WORKAROUND: For now ipv6 is not supported
88             // TODO: implement ipv6 case
89             LOG.debug("ipv6 address is not implemented yet. address {}",
90                       address);
91             new Status(StatusCode.NOTIMPLEMENTED);
92         }
93         final String prefixString = address.getHostAddress() + "/" + mask;
94         MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(prefixString));
95
96         // Set source Mac address
97         ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
98         ab.setOrder(0);
99         ab.setKey(new ActionKey(0));
100         actionList.add(ab.build());
101
102         // DecTTL
103         ab.setAction(ActionUtils.decNwTtlAction());
104         ab.setOrder(1);
105         ab.setKey(new ActionKey(1));
106         actionList.add(ab.build());
107
108         // Set Destination Tunnel ID
109         ab.setAction(ActionUtils.setTunnelIdAction(new BigInteger(destSegId)));
110         ab.setOrder(2);
111         ab.setKey(new ActionKey(2));
112         actionList.add(ab.build());
113
114         // Create Apply Actions Instruction
115         aab.setAction(actionList);
116         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
117         ib.setOrder(0);
118         ib.setKey(new InstructionKey(0));
119         instructions.add(ib.build());
120
121         // Goto Next Table
122         ib = getMutablePipelineInstructionBuilder();
123         ib.setOrder(2);
124         ib.setKey(new InstructionKey(2));
125         instructions.add(ib.build());
126
127         FlowBuilder flowBuilder = new FlowBuilder();
128         flowBuilder.setMatch(matchBuilder.build());
129         flowBuilder.setInstructions(isb.setInstruction(instructions).build());
130
131         String flowId = "Routing_" + sourceSegId + "_" + destSegId + "_" + prefixString;
132         flowBuilder.setId(new FlowId(flowId));
133         FlowKey key = new FlowKey(new FlowId(flowId));
134         flowBuilder.setBarrier(true);
135         flowBuilder.setTableId(this.getTable());
136         flowBuilder.setKey(key);
137         flowBuilder.setPriority(2048);
138         flowBuilder.setFlowName(flowId);
139         flowBuilder.setHardTimeout(0);
140         flowBuilder.setIdleTimeout(0);
141
142         if (action.equals(Action.ADD)) {
143             writeFlow(flowBuilder, nodeBuilder);
144         } else {
145             removeFlow(flowBuilder, nodeBuilder);
146         }
147
148         // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
149         return new Status(StatusCode.SUCCESS);
150     }
151
152     @Override
153     public Status programDefaultRouteEntry(Long dpid, String segmentationId, String macAddress,
154                                            InetAddress nextHop, Action action) {
155
156         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
157
158         MatchBuilder matchBuilder = new MatchBuilder();
159         NodeBuilder nodeBuilder = OF13Provider.createNodeBuilder(nodeName);
160
161         MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
162
163         // Instructions List Stores Individual Instructions
164         InstructionsBuilder isb = new InstructionsBuilder();
165         List<Instruction> instructions = Lists.newArrayList();
166         InstructionBuilder ib = new InstructionBuilder();
167         ApplyActionsBuilder aab = new ApplyActionsBuilder();
168         ActionBuilder ab = new ActionBuilder();
169         List<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> actionList = Lists.newArrayList();
170
171
172         // Set source Mac address
173         ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
174         ab.setOrder(0);
175         ab.setKey(new ActionKey(0));
176         actionList.add(ab.build());
177
178         // DecTTL
179         ab.setAction(ActionUtils.decNwTtlAction());
180         ab.setOrder(1);
181         ab.setKey(new ActionKey(1));
182         actionList.add(ab.build());
183
184         // Create Apply Actions Instruction
185         aab.setAction(actionList);
186         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
187         ib.setOrder(0);
188         ib.setKey(new InstructionKey(0));
189         instructions.add(ib.build());
190
191         // Goto Next Table
192         ib = getMutablePipelineInstructionBuilder();
193         ib.setOrder(1);
194         ib.setKey(new InstructionKey(1));
195         instructions.add(ib.build());
196
197         FlowBuilder flowBuilder = new FlowBuilder();
198         flowBuilder.setMatch(matchBuilder.build());
199         flowBuilder.setInstructions(isb.setInstruction(instructions).build());
200
201         String flowId = "DefaultRoute_" + nextHop.getHostAddress();
202         flowBuilder.setId(new FlowId(flowId));
203         FlowKey key = new FlowKey(new FlowId(flowId));
204         flowBuilder.setBarrier(true);
205         flowBuilder.setTableId(this.getTable());
206         flowBuilder.setKey(key);
207         flowBuilder.setPriority(1024);
208         flowBuilder.setFlowName(flowId);
209         flowBuilder.setHardTimeout(0);
210         flowBuilder.setIdleTimeout(0);
211
212         if (action.equals(Action.ADD)) {
213             writeFlow(flowBuilder, nodeBuilder);
214         } else {
215             removeFlow(flowBuilder, nodeBuilder);
216         }
217
218         // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
219         return new Status(StatusCode.SUCCESS);
220     }
221
222     @Override
223     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
224         super.setDependencies(bundleContext.getServiceReference(RoutingProvider.class.getName()), this);
225     }
226
227     @Override
228     public void setDependencies(Object impl) {
229
230     }
231 }