20ab07c08e609c9ded9dad5d948e745ce7741275
[netvirt.git] /
1 /*
2  * Copyright (c) 2016 NEC Corporation 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.util.ArrayList;
13 import java.util.List;
14 import org.opendaylight.netvirt.openstack.netvirt.api.L2ForwardingLearnProvider;
15 import org.opendaylight.netvirt.openstack.netvirt.api.LearnConstants;
16 import org.opendaylight.netvirt.openstack.netvirt.api.LearnConstants.LearnFlowModsType;
17 import org.opendaylight.netvirt.openstack.netvirt.providers.ConfigInterface;
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.utils.mdsal.openflow.FlowUtils;
21 import org.opendaylight.netvirt.utils.mdsal.openflow.MatchUtils;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCaseBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCaseBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromFieldBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValueBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoFieldBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoFieldBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPortBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionLearnNodesNodeTableFlowApplyActionsCaseBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.learn.grouping.NxLearnBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.learn.grouping.nx.learn.FlowMods;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.learn.grouping.nx.learn.FlowModsBuilder;
50 import org.osgi.framework.BundleContext;
51 import org.osgi.framework.ServiceReference;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55 public class L2ForwardingLearnService  extends AbstractServiceInstance implements ConfigInterface, L2ForwardingLearnProvider {
56     private static final Logger LOG = LoggerFactory.getLogger(L2ForwardingLearnService.class);
57
58     public L2ForwardingLearnService() {
59         super(Service.L2_LEARN);
60     }
61
62     public L2ForwardingLearnService(Service service) {
63         super(service);
64     }
65
66     /*
67      * (Table:L2ForwardingLearn) Remote Tep Learning
68      * Match: reg0 = ClassifierService.REG_VALUE_FROM_REMOTE
69      * Action: learn and goto next table
70      * table=105,reg0=0x2 actions=learn(table=110,hard_timeout=300,priority=16400,NXM_NX_TUN_ID[],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],output:NXM_OF_IN_PORT[]),goto_table:110
71      */
72     @Override
73     public void programL2ForwardingLearnRule(Long dpidLong) {
74         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
75         FlowBuilder flowBuilder = new FlowBuilder();
76         String flowName = "L2ForwardingLearn";
77         FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable());
78         List<Action> listAction = new ArrayList<>();
79
80         MatchBuilder matchBuilder = new MatchBuilder();
81         MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_REMOTE));
82         flowBuilder.setMatch(matchBuilder.build());
83
84         // Create learn action
85
86         /*
87          * learn header
88          * 0 1 2 3 4 5 6 7 idleTO hardTO prio cook flags table finidle finhard
89          *
90          * learn flowmod
91          * 0 1 2 3 learnFlowModType srcField dstField FlowModNumBits
92          */
93         String[] header = new String[] {
94                 "0", "300", "16400", "0", "0", "110", "0", "0"
95         };
96
97         String[][] flowMod = new String[3][];
98         // NXM_NX_TUN_ID[]
99         flowMod[0] = new String[] { LearnConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
100                 LearnConstants.NxmOfFieldType.NXM_NX_TUN_ID.getHexType(),
101                 LearnConstants.NxmOfFieldType.NXM_NX_TUN_ID.getHexType(),
102                 LearnConstants.NxmOfFieldType.NXM_NX_TUN_ID.getFlowModHeaderLen() };
103         // NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]
104         flowMod[1] = new String[] { LearnConstants.LearnFlowModsType.MATCH_FROM_FIELD.name(),
105                 LearnConstants.NxmOfFieldType.NXM_OF_ETH_SRC.getHexType(),
106                 LearnConstants.NxmOfFieldType.NXM_OF_ETH_DST.getHexType(),
107                 LearnConstants.NxmOfFieldType.NXM_OF_ETH_DST.getFlowModHeaderLen()};
108         // output:NXM_OF_IN_PORT[]
109         flowMod[2] = new String[] { LearnConstants.LearnFlowModsType.OUTPUT_TO_PORT.name(),
110                 LearnConstants.NxmOfFieldType.NXM_OF_IN_PORT.getHexType(),
111                 LearnConstants.NxmOfFieldType.NXM_OF_IN_PORT.getFlowModHeaderLen() };
112
113         listAction.add(buildAction(0, header, flowMod));
114
115         ApplyActions applyActions = new ApplyActionsBuilder().setAction(listAction).build();
116         ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build();
117         InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
118         InstructionBuilder instructionBuilder = new InstructionBuilder();
119         List<Instruction> instructions = new ArrayList<>();
120
121         instructionBuilder.setInstruction(applyActionsCase);
122         instructionBuilder.setOrder(0);
123         instructionBuilder.setKey(new InstructionKey(0));
124         instructions.add(instructionBuilder.build());
125
126         // Next service GOTO Instructions Need to be appended to the List
127         instructionBuilder = this.getMutablePipelineInstructionBuilder();
128         instructionBuilder.setOrder(1);
129         instructionBuilder.setKey(new InstructionKey(1));
130         instructions.add(instructionBuilder.build());
131
132         // Add InstructionBuilder to the Instruction(s)Builder List
133         instructionsBuilder.setInstruction(instructions);
134
135         // Add InstructionsBuilder to FlowBuilder
136         flowBuilder.setInstructions(instructionsBuilder.build());
137
138         writeFlow(flowBuilder, nodeBuilder);
139
140     }
141
142     /*
143      * build Action
144      *
145      * copy from org.opendaylight.genius.mdsalutil.ActionType.learn
146      */
147     private Action buildAction(int newActionKey, String[] header, String[][] actionValues) {
148         NxLearnBuilder learnBuilder = new NxLearnBuilder();
149         learnBuilder.setIdleTimeout(Integer.parseInt(header[0]));
150         learnBuilder.setHardTimeout(Integer.parseInt(header[1]));
151         learnBuilder.setPriority(Integer.parseInt(header[2]));
152         learnBuilder.setCookie(BigInteger.valueOf(Long.valueOf(header[3])));
153         learnBuilder.setFlags(Integer.parseInt(header[4]));
154         learnBuilder.setTableId(Short.parseShort(header[5]));
155         learnBuilder.setFinIdleTimeout(Integer.parseInt(header[6]));
156         learnBuilder.setFinHardTimeout(Integer.parseInt(header[7]));
157
158         List<FlowMods> flowModsList = new ArrayList<>();
159         for(String[] values : actionValues) {
160             if(LearnFlowModsType.MATCH_FROM_FIELD.name().equals(values[0])) {
161                 FlowModAddMatchFromFieldBuilder builder = new FlowModAddMatchFromFieldBuilder();
162                 builder.setSrcField(Long.decode(values[1]));
163                 builder.setSrcOfs(0);
164                 builder.setDstField(Long.decode(values[2]));
165                 builder.setDstOfs(0);
166                 builder.setFlowModNumBits(Integer.parseInt(values[3]));
167
168                 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
169                 FlowModAddMatchFromFieldCaseBuilder caseBuilder = new FlowModAddMatchFromFieldCaseBuilder();
170                 caseBuilder.setFlowModAddMatchFromField(builder.build());
171                 flowModsBuilder.setFlowModSpec(caseBuilder.build());
172                 flowModsList.add(flowModsBuilder.build());
173             } else if (LearnFlowModsType.MATCH_FROM_VALUE.name().equals(values[0])) {
174                 FlowModAddMatchFromValueBuilder builder = new FlowModAddMatchFromValueBuilder();
175                 builder.setValue(Integer.parseInt(values[1]));
176                 builder.setSrcField(Long.decode(values[2]));
177                 builder.setSrcOfs(0);
178                 builder.setFlowModNumBits(Integer.parseInt(values[3]));
179
180                 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
181                 FlowModAddMatchFromValueCaseBuilder caseBuilder = new FlowModAddMatchFromValueCaseBuilder();
182                 caseBuilder.setFlowModAddMatchFromValue(builder.build());
183                 flowModsBuilder.setFlowModSpec(caseBuilder.build());
184                 flowModsList.add(flowModsBuilder.build());
185             } else if (LearnFlowModsType.COPY_FROM_FIELD.name().equals(values[0])) {
186                 FlowModCopyFieldIntoFieldBuilder builder = new FlowModCopyFieldIntoFieldBuilder();
187                 builder.setSrcField(Long.decode(values[1]));
188                 builder.setSrcOfs(0);
189                 builder.setDstField(Long.decode(values[2]));
190                 builder.setDstOfs(0);
191                 builder.setFlowModNumBits(Integer.parseInt(values[3]));
192
193                 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
194                 FlowModCopyFieldIntoFieldCaseBuilder caseBuilder = new FlowModCopyFieldIntoFieldCaseBuilder();
195                 caseBuilder.setFlowModCopyFieldIntoField(builder.build());
196                 flowModsBuilder.setFlowModSpec(caseBuilder.build());
197                 flowModsList.add(flowModsBuilder.build());
198             } else if (LearnFlowModsType.COPY_FROM_VALUE.name().equals(values[0])) {
199                 FlowModCopyValueIntoFieldBuilder builder = new FlowModCopyValueIntoFieldBuilder();
200                 builder.setValue(Integer.parseInt(values[1]));
201                 builder.setDstField(Long.decode(values[2]));
202                 builder.setDstOfs(0);
203                 builder.setFlowModNumBits(Integer.parseInt(values[3]));
204
205                 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
206                 FlowModCopyValueIntoFieldCaseBuilder caseBuilder = new FlowModCopyValueIntoFieldCaseBuilder();
207                 caseBuilder.setFlowModCopyValueIntoField(builder.build());
208                 flowModsBuilder.setFlowModSpec(caseBuilder.build());
209                 flowModsList.add(flowModsBuilder.build());
210             } else if (LearnFlowModsType.OUTPUT_TO_PORT.name().equals(values[0])) {
211                 FlowModOutputToPortBuilder builder = new FlowModOutputToPortBuilder();
212                 builder.setSrcField(Long.decode(values[1]));
213                 builder.setSrcOfs(0);
214                 builder.setFlowModNumBits(Integer.parseInt(values[2]));
215
216                 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
217                 FlowModOutputToPortCaseBuilder caseBuilder = new FlowModOutputToPortCaseBuilder();
218                 caseBuilder.setFlowModOutputToPort(builder.build());
219                 flowModsBuilder.setFlowModSpec(caseBuilder.build());
220                 flowModsList.add(flowModsBuilder.build());
221             }
222         }
223         learnBuilder.setFlowMods(flowModsList);
224
225         ActionBuilder abExt = new ActionBuilder();
226         abExt.setKey(new ActionKey(newActionKey));
227
228         abExt.setAction(new NxActionLearnNodesNodeTableFlowApplyActionsCaseBuilder()
229             .setNxLearn(learnBuilder.build()).build());
230         return abExt.build();
231     }
232
233     @Override
234     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
235         super.setDependencies(bundleContext.getServiceReference(L2ForwardingLearnProvider.class.getName()), this);
236     }
237
238     @Override
239     public void setDependencies(Object impl) {
240     }
241 }