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.ControllerActionCase;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsActionCase;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbActionCase;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlDstActionCase;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetDlSrcActionCase;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetQueueActionCase;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpDstActionCase;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetTpSrcActionCase;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanIdActionCase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetVlanPcpActionCase;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
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.instruction.ApplyActionsCase;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.MeterCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
48 public class FRMUtil {
49 protected static final Logger logger = LoggerFactory.getLogger(FRMUtil.class);
50 private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
52 public static enum operation {
53 ADD, DELETE, UPDATE, GET
56 private enum EtherIPType {
60 public static boolean isNameValid(String name) {
63 if (name == null || name.trim().isEmpty() || !name.matches(NAMEREGEX)) {
70 public static boolean validateMatch(Flow flow) {
71 EtherIPType etype = EtherIPType.ANY;
72 EtherIPType ipsrctype = EtherIPType.ANY;
73 EtherIPType ipdsttype = EtherIPType.ANY;
75 Match match = flow.getMatch();
77 EthernetMatch ethernetmatch = match.getEthernetMatch();
78 IpMatch ipmatch = match.getIpMatch();
79 Layer3Match layer3match = match.getLayer3Match();
80 VlanMatch vlanmatch = match.getVlanMatch();
81 match.getIcmpv4Match();
83 if (ethernetmatch != null) {
84 if ((ethernetmatch.getEthernetSource() != null)
85 && !isL2AddressValid(ethernetmatch.getEthernetSource().getAddress().getValue())) {
87 logger.error("Ethernet source address is not valid. Example: 00:05:b9:7c:81:5f",
88 ethernetmatch.getEthernetSource());
92 if ((ethernetmatch.getEthernetDestination() != null)
93 && !isL2AddressValid(ethernetmatch.getEthernetDestination().getAddress().getValue())) {
94 logger.error("Ethernet destination address is not valid. Example: 00:05:b9:7c:81:5f",
95 ethernetmatch.getEthernetDestination());
99 if (ethernetmatch.getEthernetType() != null) {
100 long type = ethernetmatch.getEthernetType().getType().getValue().longValue();
101 if ((type < 0) || (type > 0xffff)) {
102 logger.error("Ethernet type is not valid");
105 if (type == 0x0800) {
106 etype = EtherIPType.V4;
107 } else if (type == 0x86dd) {
108 etype = EtherIPType.V6;
115 if (layer3match != null) {
116 if (layer3match instanceof Ipv4Match) {
117 if (((Ipv4Match) layer3match).getIpv4Source() != null) {
118 if (NetUtils.isIPv4AddressValid(((Ipv4Match) layer3match).getIpv4Source().getValue())) {
119 ipsrctype = EtherIPType.V4;
121 logger.error("IP source address is not valid");
125 } else if (((Ipv4Match) layer3match).getIpv4Destination() != null) {
126 if (NetUtils.isIPv4AddressValid(((Ipv4Match) layer3match).getIpv4Destination().getValue())) {
127 ipdsttype = EtherIPType.V4;
129 logger.error("IP Destination address is not valid");
134 } else if (layer3match instanceof Ipv6Match) {
135 if (((Ipv6Match) layer3match).getIpv6Source() != null) {
136 if (NetUtils.isIPv6AddressValid(((Ipv6Match) layer3match).getIpv6Source().getValue())) {
137 ipsrctype = EtherIPType.V6;
139 logger.error("IPv6 source address is not valid");
143 } else if (((Ipv6Match) layer3match).getIpv6Destination() != null) {
144 if (NetUtils.isIPv6AddressValid(((Ipv6Match) layer3match).getIpv6Destination().getValue())) {
145 ipdsttype = EtherIPType.V6;
147 logger.error("IPv6 Destination address is not valid");
155 if (etype != EtherIPType.ANY) {
156 if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
157 logger.error("Type mismatch between Ethernet & Src IP");
160 if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
161 logger.error("Type mismatch between Ethernet & Dst IP");
165 if (ipsrctype != ipdsttype) {
166 if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
167 logger.error("IP Src Dest Type mismatch");
173 if (ipmatch != null) {
174 if (ipmatch.getIpProtocol() != null && !(isProtocolValid(ipmatch.getIpProtocol().toString()))) {
175 logger.error("Protocol is not valid");
181 if (vlanmatch != null) {
182 if (vlanmatch.getVlanId() != null
183 && !(isVlanIdValid(vlanmatch.getVlanId().getVlanId().getValue().toString()))) {
184 logger.error("Vlan ID is not in the range 0 - 4095");
188 if (vlanmatch.getVlanPcp() != null
189 && !(isVlanPriorityValid(vlanmatch.getVlanPcp().getValue().toString()))) {
190 logger.error("Vlan priority is not in the range 0 - 7");
201 public static boolean validateActions(List<Action> actions) {
203 if (actions == null || actions.isEmpty()) {
204 logger.error("Actions value is null or empty");
208 for (Action curaction : actions) {
209 org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action action = curaction
211 if (action instanceof ControllerActionCase) {
212 Integer length = ((ControllerActionCase) action).getControllerAction().getMaxLength();
213 if (length < 0 || length > 65294) {
214 logger.error("Controller: MaxLength is not valid");
217 } else if (action instanceof OutputActionCase) {
218 Integer length = ((OutputActionCase) action).getOutputAction().getMaxLength();
219 Uri outputnodeconnector = ((OutputActionCase) action).getOutputAction().getOutputNodeConnector();
220 if (length < 0 || length > 65294) {
221 logger.error("OutputAction: MaxLength is not valid");
224 if (outputnodeconnector != null) {
225 if (!outputnodeconnector.getValue().equals(NodeConnectorIDType.ALL)
226 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.CONTROLLER)
227 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.HWPATH)
228 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.ONEPK)
229 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.ONEPK2OPENFLOW)
230 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.ONEPK2PCEP)
231 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.OPENFLOW)
232 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.OPENFLOW2ONEPK)
233 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.OPENFLOW2PCEP)
234 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.PCEP)
235 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.PCEP2ONEPK)
236 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.PCEP2OPENFLOW)
237 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.PRODUCTION)
238 || !outputnodeconnector.getValue().equals(NodeConnectorIDType.SWSTACK)) {
239 logger.error("Output Action: NodeConnector Type is not valid");
244 } else if (action instanceof PushMplsActionCase) {
245 Integer ethertype = ((PushMplsActionCase) action).getPushMplsAction().getEthernetType();
246 if (ethertype != null && ethertype != 0x8847 && ethertype != 0x8848) {
247 logger.error("Ether Type is not valid for PushMplsAction");
250 } else if (action instanceof PushPbbActionCase) {
251 Integer ethertype = ((PushPbbActionCase) action).getPushPbbAction().getEthernetType();
252 if (ethertype != null && ethertype != 0x88E7) {
253 logger.error("Ether type is not valid for PushPbbAction");
256 } else if (action instanceof PushVlanActionCase) {
257 Integer ethertype = ((PushVlanActionCase) action).getPushVlanAction().getEthernetType();
258 if (ethertype != null && ethertype != 0x8100 && ethertype != 0x88a8) {
259 logger.error("Ether Type is not valid for PushVlanAction");
262 } else if (action instanceof SetDlDstActionCase || action instanceof SetDlSrcActionCase) {
263 MacAddress address = ((SetDlDstActionCase) action).getSetDlDstAction().getAddress();
264 if (address != null && !isL2AddressValid(address.getValue())) {
265 logger.error("SetDlDstAction: Address not valid");
268 } else if (action instanceof SetDlSrcActionCase) {
269 MacAddress address = ((SetDlSrcActionCase) action).getSetDlSrcAction().getAddress();
270 if (address != null && !isL2AddressValid(address.getValue())) {
271 logger.error("SetDlSrcAction: Address not valid");
274 } else if (action instanceof SetQueueActionCase) {
275 String queue = ((SetQueueActionCase) action).getSetQueueAction().getQueue();
276 if (queue != null && !isQueueValid(queue)) {
277 logger.error("Queue Id not valid");
280 } else if (action instanceof SetTpDstActionCase) {
281 PortNumber port = ((SetTpDstActionCase) action).getSetTpDstAction().getPort();
282 if (port != null && !isPortValid(port)) {
283 logger.error("Port not valid");
285 } else if (action instanceof SetTpSrcActionCase) {
286 PortNumber port = ((SetTpSrcActionCase) action).getSetTpSrcAction().getPort();
287 if (port != null && !isPortValid(port)) {
288 logger.error("Port not valid");
290 } else if (action instanceof SetVlanIdActionCase) {
291 VlanId vlanid = ((SetVlanIdActionCase) action).getSetVlanIdAction().getVlanId();
292 if (vlanid != null && !isVlanIdValid(vlanid.toString())) {
293 logger.error("Vlan ID %s is not in the range 0 - 4095");
296 } else if (action instanceof SetVlanPcpActionCase) {
297 VlanPcp vlanpcp = ((SetVlanPcpActionCase) action).getSetVlanPcpAction().getVlanPcp();
298 if (vlanpcp != null && !isVlanPriorityValid(vlanpcp.toString())) {
299 logger.error("Vlan priority %s is not in the range 0 - 7");
308 public static boolean validateInstructions(Flow flow) {
309 List<Instruction> instructionsList = new ArrayList<>();
310 Instructions instructions = flow.getInstructions();
311 if (instructions == null) {
314 instructionsList = instructions.getInstruction();
316 for (Instruction instruction : instructionsList) {
317 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction curInstruction = instruction
319 if (curInstruction instanceof GoToTableCase) {
321 Short tableid = ((GoToTableCase) curInstruction).getGoToTable().getTableId();
323 logger.error("table id is not valid");
328 else if (curInstruction instanceof WriteActionsCase) {
330 List<Action> action = ((WriteActionsCase) curInstruction).getWriteActions().getAction();
331 validateActions(action);
335 else if (curInstruction instanceof ApplyActionsCase) {
336 List<Action> action = ((ApplyActionsCase) curInstruction).getApplyActions().getAction();
337 validateActions(action);
340 else if (curInstruction instanceof ClearActionsCase) {
341 List<Action> action = ((ClearActionsCase) curInstruction).getClearActions().getAction();
342 validateActions(action);
345 else if (curInstruction instanceof MeterCase) {
347 MeterId meter = ((MeterCase) curInstruction).getMeter().getMeterId();
348 if (meter != null && !isValidMeter(meter)) {
349 logger.error("Meter Id is not valid");
359 public static boolean isValidMeter(MeterId meter) {
364 public static boolean isQueueValid(String queue) {
369 public static boolean isPortValid(PortNumber port) {
374 public static boolean isL2AddressValid(String mac) {
379 Pattern macPattern = Pattern.compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
380 Matcher mm = macPattern.matcher(mac);
382 logger.debug("Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f", mac);
388 public static boolean isProtocolValid(String protocol) {
389 IPProtocols proto = IPProtocols.fromString(protocol);
390 return (proto != null);
393 public static boolean isVlanIdValid(String vlanId) {
394 int vlan = Integer.decode(vlanId);
395 return ((vlan >= 0) && (vlan < 4096));
398 public static boolean isVlanPriorityValid(String vlanPriority) {
399 int pri = Integer.decode(vlanPriority);
400 return ((pri >= 0) && (pri < 8));