Fixes for MD-FRM
[controller.git] / opendaylight / md-sal / forwardingrules-manager / src / main / java / org / opendaylight / controller / forwardingrulesmanager / consumer / impl / FRMUtil.java
1 package org.opendaylight.controller.forwardingrulesmanager.consumer.impl;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.regex.Matcher;
6 import java.util.regex.Pattern;
7
8 import org.opendaylight.controller.sal.utils.IPProtocols;
9 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
10 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
11 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerAction;
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputAction;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsAction;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbAction;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanAction;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstAction;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcAction;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueAction;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstAction;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcAction;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdAction;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpAction;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActions;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActions;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTable;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.Meter;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActions;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
42
43 public class FRMUtil {
44     protected static final Logger logger = LoggerFactory.getLogger(FRMUtil.class);
45     private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
46
47     public static enum operation {
48         ADD, DELETE, UPDATE, GET
49     };
50
51     public static boolean isNameValid(String name) {
52
53         // Name validation
54         if (name == null || name.trim().isEmpty() || !name.matches(NAMEREGEX)) {
55             return false;
56         }
57         return true;
58
59     }
60
61     public static boolean validateMatch(Flow flow) {
62         Match match = flow.getMatch();
63         if (match != null) {
64             EthernetMatch ethernetmatch = match.getEthernetMatch();
65             IpMatch ipmatch = match.getIpMatch();
66             VlanMatch vlanmatch = match.getVlanMatch();
67             match.getIcmpv4Match();
68
69             if (ethernetmatch != null) {
70                 if ((ethernetmatch.getEthernetSource() != null)
71                         && !isL2AddressValid(ethernetmatch.getEthernetSource().toString())) {
72
73                     logger.error("Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
74                             ethernetmatch.getEthernetSource());
75                     return false;
76                 }
77
78                 if ((ethernetmatch.getEthernetDestination() != null)
79                         && !isL2AddressValid(ethernetmatch.getEthernetDestination().toString())) {
80                     logger.error("Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
81                             ethernetmatch.getEthernetDestination());
82                     return false;
83                 }
84
85                 if (ethernetmatch.getEthernetType() != null) {
86                     int type = Integer.decode(ethernetmatch.getEthernetType().toString());
87                     if ((type < 0) || (type > 0xffff)) {
88                         logger.error("Ethernet type is not valid");
89                         return false;
90                     }
91                 }
92             } else if (ipmatch != null) {
93                 if (ipmatch.getIpProtocol() != null && isProtocolValid(ipmatch.getIpProtocol().toString())) {
94                     logger.error("Protocol is not valid");
95                     return false;
96                 }
97             } else if (vlanmatch != null) {
98                 if (vlanmatch.getVlanId() != null && isVlanIdValid(vlanmatch.getVlanId().toString())) {
99                     logger.error("Vlan ID is not in the range 0 - 4095");
100                     return false;
101                 }
102
103                 if (vlanmatch.getVlanPcp() != null && isVlanPriorityValid(vlanmatch.getVlanPcp().toString())) {
104                     logger.error("Vlan priority is not in the range 0 - 7");
105                     return false;
106                 }
107             }
108         }
109
110         return true;
111     }
112
113     public static boolean validateActions(List<Action> actions) {
114
115         if (actions == null || actions.isEmpty()) {
116             logger.error("Actions value is null or empty");
117             return false;
118         }
119
120         for (Action curaction : actions) {
121             org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action action = curaction
122                     .getAction();
123             if (action instanceof ControllerAction) {
124                 Integer length = ((ControllerAction) action).getMaxLength();
125                 if (length < 0 || length > 65294) {
126                     logger.error("Controller: MaxLength is not valid");
127                     return false;
128                 }
129             } else if (action instanceof OutputAction) {
130                 Integer length = ((OutputAction) action).getMaxLength();
131                 Uri outputnodeconnector = ((OutputAction) action).getOutputNodeConnector();
132                 if (length < 0 || length > 65294) {
133                     logger.error("OutputAction: MaxLength is not valid");
134                     return false;
135                 }
136                 if (outputnodeconnector != null) {
137                     // TODO
138                 }
139             } else if (action instanceof PushMplsAction) {
140                 Integer ethertype = ((PushMplsAction) action).getEthernetType();
141                 if (ethertype != null && ethertype != 0x8847 && ethertype != 0x8848) {
142                     logger.error("Ether Type is not valid for PushMplsAction");
143                     return false;
144                 }
145             } else if (action instanceof PushPbbAction) {
146                 Integer ethertype = ((PushPbbAction) action).getEthernetType();
147                 if (ethertype != null && ethertype != 0x88E7) {
148                     logger.error("Ether type is not valid for PushPbbAction");
149                     return false;
150                 }
151             } else if (action instanceof PushVlanAction) {
152                 Integer ethertype = ((PushVlanAction) action).getEthernetType();
153                 if (ethertype != null && ethertype != 0x8100 && ethertype != 0x88a8) {
154                     logger.error("Ether Type is not valid for PushVlanAction");
155                     return false;
156                 }
157             } else if (action instanceof SetDlDstAction || action instanceof SetDlSrcAction) {
158                 MacAddress address = ((SetDlDstAction) action).getAddress();
159                 if (address != null && !isL2AddressValid(address.toString())) {
160                     logger.error("SetDlDstAction: Address not valid");
161                     return false;
162                 }
163             } else if (action instanceof SetDlSrcAction) {
164                 MacAddress address = ((SetDlSrcAction) action).getAddress();
165                 if (address != null && !isL2AddressValid(address.toString())) {
166                     logger.error("SetDlSrcAction: Address not valid");
167                     return false;
168                 }
169             } else if (action instanceof SetQueueAction) {
170                 String queue = ((SetQueueAction) action).getQueue();
171                 if (queue != null && !isQueueValid(queue)) {
172                     logger.error("Queue Id not valid");
173                     return false;
174                 }
175             } else if (action instanceof SetTpDstAction) {
176                 PortNumber port = ((SetTpDstAction) action).getPort();
177                 if (port != null && !isPortValid(port)) {
178                     logger.error("Port not valid");
179                 }
180             } else if (action instanceof SetTpSrcAction) {
181                 PortNumber port = ((SetTpSrcAction) action).getPort();
182                 if (port != null && !isPortValid(port)) {
183                     logger.error("Port not valid");
184                 }
185             } else if (action instanceof SetVlanIdAction) {
186                 VlanId vlanid = ((SetVlanIdAction) action).getVlanId();
187                 if (vlanid != null && !isVlanIdValid(vlanid.toString())) {
188                     logger.error("Vlan ID %s is not in the range 0 - 4095");
189                     return false;
190                 }
191             } else if (action instanceof SetVlanPcpAction) {
192                 VlanPcp vlanpcp = ((SetVlanPcpAction) action).getVlanPcp();
193                 if (vlanpcp != null && !isVlanPriorityValid(vlanpcp.toString())) {
194                     logger.error("Vlan priority %s is not in the range 0 - 7");
195                     return false;
196                 }
197             }
198         }
199         return true;
200     }
201
202     public static boolean validateInstructions(Flow flow) {
203         List<Instruction> instructionsList = new ArrayList<>();
204         Instructions instructions = flow.getInstructions();
205         if( instructions == null ) {
206             return false;
207         }
208         instructionsList = instructions.getInstruction();
209
210         for (Instruction instruction : instructionsList) {
211             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
212                     .getInstruction();
213             if (curInstruction instanceof GoToTable) {
214
215                 Short tableid = ((GoToTable) curInstruction).getTableId();
216                 if (tableid < 0) {
217                     logger.error("table id is not valid");
218                     return false;
219                 }
220             }
221
222             else if (curInstruction instanceof WriteActions) {
223
224                 List<Action> action = ((WriteActions) curInstruction).getAction();
225                 validateActions(action);
226
227             }
228
229             else if (curInstruction instanceof ApplyActions) {
230                 List<Action> action = ((ApplyActions) curInstruction).getAction();
231                 validateActions(action);
232             }
233
234             else if (curInstruction instanceof ClearActions) {
235                 List<Action> action = ((ClearActions) curInstruction).getAction();
236                 validateActions(action);
237             }
238
239             else if (curInstruction instanceof Meter) {
240
241                 String meter = ((Meter) curInstruction).getMeter();
242                 if (meter != null && !isValidMeter(meter)) {
243                     logger.error("Meter Id is not valid");
244                     return false;
245                 }
246             }
247
248         }
249
250         return true;
251     }
252
253     public static boolean isValidMeter(String meter) {
254         // TODO
255         return true;
256     }
257
258     public static boolean isQueueValid(String queue) {
259         // TODO
260         return true;
261     }
262
263     public static boolean isPortValid(PortNumber port) {
264         // TODO
265         return true;
266     }
267
268     public static boolean isL2AddressValid(String mac) {
269         if (mac == null) {
270             return false;
271         }
272
273         Pattern macPattern = Pattern.compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
274         Matcher mm = macPattern.matcher(mac);
275         if (!mm.matches()) {
276             logger.debug("Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f", mac);
277             return false;
278         }
279         return true;
280     }
281
282     public static boolean isProtocolValid(String protocol) {
283         IPProtocols proto = IPProtocols.fromString(protocol);
284         return (proto != null);
285     }
286
287     public static boolean isVlanIdValid(String vlanId) {
288         int vlan = Integer.decode(vlanId);
289         return ((vlan >= 0) && (vlan < 4096));
290     }
291
292     public static boolean isVlanPriorityValid(String vlanPriority) {
293         int pri = Integer.decode(vlanPriority);
294         return ((pri >= 0) && (pri < 8));
295     }
296 }