Initial pass at changing groupId
[netvirt.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / netvirt / 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.netvirt.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.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;
41
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;
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         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);
68         }
69
70         SubnetUtils addressSubnetInfo = new SubnetUtils(address.getHostAddress() + "/" + mask);
71         final String prefixString = addressSubnetInfo.getInfo().getNetworkAddress() + "/" + mask;
72
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);
77
78         boolean isExternalNet = sourceSegId.equals(Constants.EXTERNAL_NETWORK);
79         MatchBuilder matchBuilder = new MatchBuilder();
80         if (isExternalNet) {
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)));
85         } else {
86             MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(sourceSegId));
87         }
88
89         MatchUtils.createDstL3IPv4Match(matchBuilder, new Ipv4Prefix(prefixString));
90         flowBuilder.setMatch(matchBuilder.build());
91
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();
101
102             //if this is an east<->west route, save the src mac in case this is an ICMP echo request
103             if(!isExternalNet) {
104                 ab.setAction(ActionUtils.nxMoveRegAction(
105                                             new SrcOfEthSrcCaseBuilder().setOfEthSrc(Boolean.TRUE).build(),
106                                             new DstNxRegCaseBuilder().setNxReg(IcmpEchoResponderService.SRC_MAC_4_HIGH_BYTES_FIELD).build(),
107                                             0,0,31, false));
108                 ab.setOrder(actionList.size());
109                 ab.setKey(new ActionKey(actionList.size()));
110                 actionList.add(ab.build());
111
112                 ab.setAction(ActionUtils.nxMoveRegAction(
113                                             new SrcOfEthSrcCaseBuilder().setOfEthSrc(Boolean.TRUE).build(),
114                                             new DstNxRegCaseBuilder().setNxReg(IcmpEchoResponderService.SRC_MAC_2_LOW_BYTES_FIELD).build(),
115                                             32,0,15, false));
116                 ab.setOrder(actionList.size());
117                 ab.setKey(new ActionKey(actionList.size()));
118                 actionList.add(ab.build());
119             }
120
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());
126
127             // DecTTL
128             ab.setAction(ActionUtils.decNwTtlAction());
129             ab.setOrder(actionList.size());
130             ab.setKey(new ActionKey(actionList.size()));
131             actionList.add(ab.build());
132
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());
138
139             // Create Apply Actions Instruction
140             aab.setAction(actionList);
141             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
142             ib.setOrder(0);
143             ib.setKey(new InstructionKey(0));
144             instructions.add(ib.build());
145
146             // Goto Next Table
147             ib = getMutablePipelineInstructionBuilder();
148             ib.setOrder(2);
149             ib.setKey(new InstructionKey(2));
150             instructions.add(ib.build());
151
152             flowBuilder.setInstructions(isb.setInstruction(instructions).build());
153             writeFlow(flowBuilder, nodeBuilder);
154         } else {
155             removeFlow(flowBuilder, nodeBuilder);
156         }
157
158         // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
159         return new Status(StatusCode.SUCCESS);
160     }
161
162     @Override
163     public Status programDefaultRouteEntry(Long dpid, String segmentationId, String macAddress,
164                                            InetAddress nextHop, Action action) {
165
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);
170
171         MatchBuilder matchBuilder = new MatchBuilder();
172         MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
173         flowBuilder.setMatch(matchBuilder.build());
174
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();
184
185             // Set source Mac address
186             ab.setAction(ActionUtils.setDlSrcAction(new MacAddress(macAddress)));
187             ab.setOrder(0);
188             ab.setKey(new ActionKey(0));
189             actionList.add(ab.build());
190
191             // DecTTL
192             ab.setAction(ActionUtils.decNwTtlAction());
193             ab.setOrder(1);
194             ab.setKey(new ActionKey(1));
195             actionList.add(ab.build());
196
197             // Create Apply Actions Instruction
198             aab.setAction(actionList);
199             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
200             ib.setOrder(0);
201             ib.setKey(new InstructionKey(0));
202             instructions.add(ib.build());
203
204             // Goto Next Table
205             ib = getMutablePipelineInstructionBuilder();
206             ib.setOrder(1);
207             ib.setKey(new InstructionKey(1));
208             instructions.add(ib.build());
209
210             flowBuilder.setInstructions(isb.setInstruction(instructions).build());
211
212             writeFlow(flowBuilder, nodeBuilder);
213         } else {
214             removeFlow(flowBuilder, nodeBuilder);
215         }
216
217         // ToDo: WriteFlow/RemoveFlow should return something we can use to check success
218         return new Status(StatusCode.SUCCESS);
219     }
220
221     @Override
222     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
223         super.setDependencies(bundleContext.getServiceReference(RoutingProvider.class.getName()), this);
224     }
225
226     @Override
227     public void setDependencies(Object impl) {
228
229     }
230 }