1 package org.opendaylight.controller.forwardingrulesmanager.consumer.impl;
3 import java.util.ArrayList;
5 import java.util.regex.Matcher;
6 import java.util.regex.Pattern;
8 import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
9 import org.opendaylight.controller.sal.utils.IPProtocols;
10 import org.opendaylight.controller.sal.utils.NetUtils;
11 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
12 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
13 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.ControllerAction;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputAction;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsAction;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbAction;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanAction;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstAction;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcAction;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueAction;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstAction;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcAction;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdAction;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpAction;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActions;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActions;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTable;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.Meter;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActions;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 public class FRMUtil {
48 protected static final Logger logger = LoggerFactory.getLogger(FRMUtil.class);
49 private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
51 public static enum operation {
52 ADD, DELETE, UPDATE, GET
55 private enum EtherIPType {
59 public static boolean isNameValid(String name) {
62 if (name == null || name.trim().isEmpty() || !name.matches(NAMEREGEX)) {
69 public static boolean validateMatch(Flow flow) {
70 EtherIPType etype = EtherIPType.ANY;
71 EtherIPType ipsrctype = EtherIPType.ANY;
72 EtherIPType ipdsttype = EtherIPType.ANY;
74 Match match = flow.getMatch();
76 EthernetMatch ethernetmatch = match.getEthernetMatch();
77 IpMatch ipmatch = match.getIpMatch();
78 Layer3Match layer3match = match.getLayer3Match();
79 VlanMatch vlanmatch = match.getVlanMatch();
80 match.getIcmpv4Match();
82 if (ethernetmatch != null) {
83 if ((ethernetmatch.getEthernetSource() != null)
84 && !isL2AddressValid(ethernetmatch.getEthernetSource().getAddress().getValue())) {
86 logger.error("Ethernet source address is not valid. Example: 00:05:b9:7c:81:5f",
87 ethernetmatch.getEthernetSource());
91 if ((ethernetmatch.getEthernetDestination() != null)
92 && !isL2AddressValid(ethernetmatch.getEthernetDestination().getAddress().getValue())) {
93 logger.error("Ethernet destination address is not valid. Example: 00:05:b9:7c:81:5f",
94 ethernetmatch.getEthernetDestination());
98 if (ethernetmatch.getEthernetType() != null) {
99 long type = ethernetmatch.getEthernetType().getType().getValue().longValue();
100 if ((type < 0) || (type > 0xffff)) {
101 logger.error("Ethernet type is not valid");
104 if (type == 0x0800) {
105 etype = EtherIPType.V4;
106 } else if (type == 0x86dd) {
107 etype = EtherIPType.V6;
114 if (layer3match != null) {
115 if (layer3match instanceof Ipv4Match) {
116 if (((Ipv4Match) layer3match).getIpv4Source() != null) {
117 if (NetUtils.isIPv4AddressValid(((Ipv4Match) layer3match).getIpv4Source().getValue())) {
118 ipsrctype = EtherIPType.V4;
120 logger.error("IP source address is not valid");
124 } else if (((Ipv4Match) layer3match).getIpv4Destination() != null) {
125 if (NetUtils.isIPv4AddressValid(((Ipv4Match) layer3match).getIpv4Destination().getValue())) {
126 ipdsttype = EtherIPType.V4;
128 logger.error("IP Destination address is not valid");
133 } else if (layer3match instanceof Ipv6Match) {
134 if (((Ipv6Match) layer3match).getIpv6Source() != null) {
135 if (NetUtils.isIPv6AddressValid(((Ipv6Match) layer3match).getIpv6Source().getValue())) {
136 ipsrctype = EtherIPType.V6;
138 logger.error("IPv6 source address is not valid");
142 } else if (((Ipv6Match) layer3match).getIpv6Destination() != null) {
143 if (NetUtils.isIPv6AddressValid(((Ipv6Match) layer3match).getIpv6Destination().getValue())) {
144 ipdsttype = EtherIPType.V6;
146 logger.error("IPv6 Destination address is not valid");
154 if (etype != EtherIPType.ANY) {
155 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
156 logger.error("Type mismatch between Ethernet & Src IP");
159 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
160 logger.error("Type mismatch between Ethernet & Dst IP");
164 if (ipsrctype != ipdsttype) {
165 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
166 logger.error("IP Src Dest Type mismatch");
172 if (ipmatch != null) {
173 if (ipmatch.getIpProtocol() != null && !(isProtocolValid(ipmatch.getIpProtocol().toString()))) {
174 logger.error("Protocol is not valid");
180 if (vlanmatch != null) {
181 if (vlanmatch.getVlanId() != null
182 && !(isVlanIdValid(vlanmatch.getVlanId().getVlanId().getValue().toString()))) {
183 logger.error("Vlan ID is not in the range 0 - 4095");
187 if (vlanmatch.getVlanPcp() != null
188 && !(isVlanPriorityValid(vlanmatch.getVlanPcp().getValue().toString()))) {
189 logger.error("Vlan priority is not in the range 0 - 7");
200 public static boolean validateActions(List<Action> actions) {
202 if (actions == null || actions.isEmpty()) {
203 logger.error("Actions value is null or empty");
207 for (Action curaction : actions) {
208 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action action = curaction
210 if (action instanceof ControllerAction) {
211 Integer length = ((ControllerAction) action).getMaxLength();
212 if (length < 0 || length > 65294) {
213 logger.error("Controller: MaxLength is not valid");
216 } else if (action instanceof OutputAction) {
217 Integer length = ((OutputAction) action).getMaxLength();
218 Uri outputnodeconnector = ((OutputAction) action).getOutputNodeConnector();
219 if (length < 0 || length > 65294) {
220 logger.error("OutputAction: MaxLength is not valid");
223 if (outputnodeconnector != null) {
224 if (!outputnodeconnector.getValue().equals(NodeConnectorIDType.ALL)
225 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.CONTROLLER)
226 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.HWPATH)
227 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.ONEPK)
228 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.ONEPK2OPENFLOW)
229 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.ONEPK2PCEP)
230 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.OPENFLOW)
231 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.OPENFLOW2ONEPK)
232 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.OPENFLOW2PCEP)
233 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.PCEP)
234 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.PCEP2ONEPK)
235 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.PCEP2OPENFLOW)
236 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.PRODUCTION)
237 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.SWSTACK)) {
238 logger.error("Output Action: NodeConnector Type is not valid");
243 } else if (action instanceof PushMplsAction) {
244 Integer ethertype = ((PushMplsAction) action).getEthernetType();
245 if (ethertype != null && ethertype != 0x8847 && ethertype != 0x8848) {
246 logger.error("Ether Type is not valid for PushMplsAction");
249 } else if (action instanceof PushPbbAction) {
250 Integer ethertype = ((PushPbbAction) action).getEthernetType();
251 if (ethertype != null && ethertype != 0x88E7) {
252 logger.error("Ether type is not valid for PushPbbAction");
255 } else if (action instanceof PushVlanAction) {
256 Integer ethertype = ((PushVlanAction) action).getEthernetType();
257 if (ethertype != null && ethertype != 0x8100 && ethertype != 0x88a8) {
258 logger.error("Ether Type is not valid for PushVlanAction");
261 } else if (action instanceof SetDlDstAction) {
262 MacAddress address = ((SetDlDstAction) action).getAddress();
263 if (address != null && !isL2AddressValid(address.getValue())) {
264 logger.error("SetDlDstAction: Address not valid");
267 } else if (action instanceof SetDlSrcAction) {
268 MacAddress address = ((SetDlSrcAction) action).getAddress();
269 if (address != null && !isL2AddressValid(address.getValue())) {
270 logger.error("SetDlSrcAction: Address not valid");
273 } else if (action instanceof SetQueueAction) {
274 String queue = ((SetQueueAction) action).getQueue();
275 if (queue != null && !isQueueValid(queue)) {
276 logger.error("Queue Id not valid");
279 } else if (action instanceof SetTpDstAction) {
280 PortNumber port = ((SetTpDstAction) action).getPort();
281 if (port != null && !isPortValid(port)) {
282 logger.error("Port not valid");
284 } else if (action instanceof SetTpSrcAction) {
285 PortNumber port = ((SetTpSrcAction) action).getPort();
286 if (port != null && !isPortValid(port)) {
287 logger.error("Port not valid");
289 } else if (action instanceof SetVlanIdAction) {
290 VlanId vlanid = ((SetVlanIdAction) action).getVlanId();
291 if (vlanid != null && !isVlanIdValid(vlanid.getValue().toString())) {
292 logger.error("Vlan ID is not in the range 0 - 4095");
295 } else if (action instanceof SetVlanPcpAction) {
296 VlanPcp vlanpcp = ((SetVlanPcpAction) action).getVlanPcp();
297 if (vlanpcp != null && !isVlanPriorityValid(vlanpcp.getValue().toString())) {
298 logger.error("Vlan priority is not in the range 0 - 7");
307 public static boolean validateInstructions(Flow flow) {
308 List<Instruction> instructionsList = new ArrayList<>();
309 Instructions instructions = flow.getInstructions();
310 if (instructions == null) {
313 instructionsList = instructions.getInstruction();
315 for (Instruction instruction : instructionsList) {
316 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
318 if (curInstruction instanceof GoToTable) {
320 Short tableid = ((GoToTable) curInstruction).getTableId();
322 logger.error("table id is not valid");
327 else if (curInstruction instanceof WriteActions) {
329 List<Action> action = ((WriteActions) curInstruction).getAction();
330 validateActions(action);
334 else if (curInstruction instanceof ApplyActions) {
335 List<Action> action = ((ApplyActions) curInstruction).getAction();
336 validateActions(action);
339 else if (curInstruction instanceof ClearActions) {
340 List<Action> action = ((ClearActions) curInstruction).getAction();
341 validateActions(action);
344 else if (curInstruction instanceof Meter) {
346 String meter = ((Meter) curInstruction).getMeter();
347 if (meter != null && !isValidMeter(meter)) {
348 logger.error("Meter Id is not valid");
358 public static boolean isValidMeter(String meter) {
363 public static boolean isQueueValid(String queue) {
368 public static boolean isPortValid(PortNumber port) {
373 public static boolean isL2AddressValid(String mac) {
378 Pattern macPattern = Pattern.compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
379 Matcher mm = macPattern.matcher(mac);
381 logger.debug("Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f", mac);
387 public static boolean isProtocolValid(String protocol) {
388 IPProtocols proto = IPProtocols.fromString(protocol);
389 return (proto != null);
392 public static boolean isVlanIdValid(String vlanId) {
393 int vlan = Integer.decode(vlanId);
394 return ((vlan >= 0) && (vlan < 4096));
397 public static boolean isVlanPriorityValid(String vlanPriority) {
398 int pri = Integer.decode(vlanPriority);
399 return ((pri >= 0) && (pri < 8));