bdea09da70ae99fc9ad2a4147e1a0e92add28bcc
[onosfw.git] /
1 /*
2  * Copyright 2014-2015 Open Networking Laboratory
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.onosproject.provider.of.flow.impl;
17
18 import org.onlab.packet.Ip4Address;
19 import org.onosproject.net.PortNumber;
20 import org.onosproject.net.driver.DriverService;
21 import org.onosproject.net.flow.FlowRule;
22 import org.onosproject.net.flow.TrafficTreatment;
23 import org.onosproject.net.flow.instructions.Instruction;
24 import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
25 import org.onosproject.net.flow.instructions.Instructions.SetQueueInstruction;
26 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
27 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
28 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
29 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
30 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
31 import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
32 import org.projectfloodlight.openflow.protocol.OFFactory;
33 import org.projectfloodlight.openflow.protocol.OFFlowAdd;
34 import org.projectfloodlight.openflow.protocol.OFFlowDelete;
35 import org.projectfloodlight.openflow.protocol.OFFlowMod;
36 import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
37 import org.projectfloodlight.openflow.protocol.action.OFAction;
38 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
39 import org.projectfloodlight.openflow.protocol.action.OFActionEnqueue;
40 import org.projectfloodlight.openflow.protocol.match.Match;
41 import org.projectfloodlight.openflow.types.IPv4Address;
42 import org.projectfloodlight.openflow.types.MacAddress;
43 import org.projectfloodlight.openflow.types.OFBufferId;
44 import org.projectfloodlight.openflow.types.OFPort;
45 import org.projectfloodlight.openflow.types.U64;
46 import org.projectfloodlight.openflow.types.VlanPcp;
47 import org.projectfloodlight.openflow.types.VlanVid;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 import java.util.Collections;
52 import java.util.LinkedList;
53 import java.util.List;
54 import java.util.Optional;
55
56 /**
57  * Flow mod builder for OpenFlow 1.0.
58  */
59 public class FlowModBuilderVer10 extends FlowModBuilder {
60
61     private final Logger log = LoggerFactory.getLogger(getClass());
62     private static final int OFPCML_NO_BUFFER = 0xffff;
63
64     private final TrafficTreatment treatment;
65
66     /**
67      * Constructor for a flow mod builder for OpenFlow 1.0.
68      *
69      * @param flowRule the flow rule to transform into a flow mod
70      * @param factory the OpenFlow factory to use to build the flow mod
71      * @param xid the transaction ID
72      * @param driverService the device driver service
73      */
74     protected FlowModBuilderVer10(FlowRule flowRule,
75                                   OFFactory factory, Optional<Long> xid,
76                                   Optional<DriverService> driverService) {
77         super(flowRule, factory, xid, driverService);
78
79         this.treatment = flowRule.treatment();
80     }
81
82     @Override
83     public OFFlowAdd buildFlowAdd() {
84         Match match = buildMatch();
85         List<OFAction> actions = buildActions();
86
87         long cookie = flowRule().id().value();
88
89
90         OFFlowAdd fm = factory().buildFlowAdd()
91                 .setXid(xid)
92                 .setCookie(U64.of(cookie))
93                 .setBufferId(OFBufferId.NO_BUFFER)
94                 .setActions(actions)
95                 .setMatch(match)
96                 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
97                 .setPriority(flowRule().priority())
98                 .build();
99
100         return fm;
101     }
102
103     @Override
104     public OFFlowMod buildFlowMod() {
105         Match match = buildMatch();
106         List<OFAction> actions = buildActions();
107
108         long cookie = flowRule().id().value();
109
110         OFFlowMod fm = factory().buildFlowModify()
111                 .setXid(xid)
112                 .setCookie(U64.of(cookie))
113                 .setBufferId(OFBufferId.NO_BUFFER)
114                 .setActions(actions)
115                 .setMatch(match)
116                 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
117                 .setPriority(flowRule().priority())
118                 .build();
119
120         return fm;
121     }
122
123     @Override
124     public OFFlowDelete buildFlowDel() {
125         Match match = buildMatch();
126
127         long cookie = flowRule().id().value();
128
129         OFFlowDelete fm = factory().buildFlowDelete()
130                 .setXid(xid)
131                 .setCookie(U64.of(cookie))
132                 .setBufferId(OFBufferId.NO_BUFFER)
133                 .setMatch(match)
134                 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
135                 .setPriority(flowRule().priority())
136                 .build();
137
138         return fm;
139     }
140
141     private List<OFAction> buildActions() {
142         List<OFAction> acts = new LinkedList<>();
143         OFAction act;
144         if (treatment == null) {
145             return acts;
146         }
147         for (Instruction i : treatment.immediate()) {
148             switch (i.type()) {
149             case DROP:
150             case NOACTION:
151                 return Collections.emptyList();
152             case L2MODIFICATION:
153                 act = buildL2Modification(i);
154                 if (act != null) {
155                     acts.add(buildL2Modification(i));
156                 }
157                 break;
158             case L3MODIFICATION:
159                 act = buildL3Modification(i);
160                 if (act != null) {
161                     acts.add(buildL3Modification(i));
162                 }
163                 break;
164             case OUTPUT:
165                 OutputInstruction out = (OutputInstruction) i;
166                 OFActionOutput.Builder action = factory().actions().buildOutput()
167                         .setPort(OFPort.of((int) out.port().toLong()));
168                 if (out.port().equals(PortNumber.CONTROLLER)) {
169                     action.setMaxLen(OFPCML_NO_BUFFER);
170                 }
171                 acts.add(action.build());
172                 break;
173             case QUEUE:
174                 SetQueueInstruction queue = (SetQueueInstruction) i;
175                 if (queue.port() == null) {
176                     log.warn("Required argument 'port' undefined for OFActionEnqueue");
177                 }
178                 OFActionEnqueue.Builder queueBuilder = factory().actions().buildEnqueue()
179                         .setQueueId(queue.queueId())
180                         .setPort(OFPort.ofInt((int) queue.port().toLong()));
181                 acts.add(queueBuilder.build());
182                 break;
183             case L0MODIFICATION:
184             case GROUP:
185             case TABLE:
186             case METADATA:
187                 log.warn("Instruction type {} not supported with protocol version {}",
188                         i.type(), factory().getVersion());
189                 break;
190             default:
191                 log.warn("Instruction type {} not yet implemented.", i.type());
192             }
193         }
194
195         return acts;
196     }
197
198     private OFAction buildL3Modification(Instruction i) {
199         L3ModificationInstruction l3m = (L3ModificationInstruction) i;
200         ModIPInstruction ip;
201         Ip4Address ip4;
202         switch (l3m.subtype()) {
203         case IPV4_SRC:
204             ip = (ModIPInstruction) i;
205             ip4 = ip.ip().getIp4Address();
206             return factory().actions().setNwSrc(IPv4Address.of(ip4.toInt()));
207         case IPV4_DST:
208             ip = (ModIPInstruction) i;
209             ip4 = ip.ip().getIp4Address();
210             return factory().actions().setNwDst(IPv4Address.of(ip4.toInt()));
211         default:
212             log.warn("Unimplemented action type {}.", l3m.subtype());
213             break;
214         }
215         return null;
216     }
217
218     private OFAction buildL2Modification(Instruction i) {
219         L2ModificationInstruction l2m = (L2ModificationInstruction) i;
220         ModEtherInstruction eth;
221         switch (l2m.subtype()) {
222         case ETH_DST:
223             eth = (ModEtherInstruction) l2m;
224             return factory().actions().setDlDst(MacAddress.of(eth.mac().toLong()));
225         case ETH_SRC:
226             eth = (ModEtherInstruction) l2m;
227             return factory().actions().setDlSrc(MacAddress.of(eth.mac().toLong()));
228         case VLAN_ID:
229             ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
230             return factory().actions().setVlanVid(VlanVid.ofVlan(vlanId.vlanId().toShort()));
231         case VLAN_PCP:
232             ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
233             return factory().actions().setVlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
234         case VLAN_POP:
235             return factory().actions().stripVlan();
236         case VLAN_PUSH:
237             return null;
238         default:
239             log.warn("Unimplemented action type {}.", l2m.subtype());
240             break;
241         }
242         return null;
243     }
244
245 }