blob: c4cb6bca85428e93b6b52c45f8c63c3d33e5bf31 [file] [log] [blame]
Andreas Wundsamf89f7822013-09-23 14:49:24 -07001 @SuppressWarnings("unchecked")
2 @Override
3 public <F extends OFValueType<F>> F get(MatchField<F> field)
4 throws UnsupportedOperationException {
5 if (isFullyWildcarded(field))
6 return null;
Andreas Wundsambc679f72013-08-01 22:13:09 -07007
Andreas Wundsamf89f7822013-09-23 14:49:24 -07008 Object result;
9 switch (field.id) {
10 case IN_PORT:
11 result = inPort;
12 break;
13 case ETH_DST:
14 result = ethDst;
15 break;
16 case ETH_SRC:
17 result = ethSrc;
18 break;
19 case ETH_TYPE:
20 result = ethType;
21 break;
22 case VLAN_VID:
23 result = vlanVid;
24 break;
25 case VLAN_PCP:
26 result = vlanPcp;
27 break;
Rob Vaterlausf13323d2013-10-10 13:30:29 -070028 case ARP_OP:
29 result = ArpOpcode.of(ipProto.getIpProtocolNumber());
30 break;
31 case ARP_SPA:
32 result = ipv4Src;
33 break;
34 case ARP_TPA:
35 result = ipv4Dst;
36 break;
Andreas Wundsamf89f7822013-09-23 14:49:24 -070037 case IP_DSCP:
38 result = ipDscp;
39 break;
40 case IP_PROTO:
41 result = ipProto;
42 break;
43 case IPV4_SRC:
Rob Vaterlausf13323d2013-10-10 13:30:29 -070044 result = ipv4Src;
Andreas Wundsamf89f7822013-09-23 14:49:24 -070045 break;
46 case IPV4_DST:
47 result = ipv4Dst;
48 break;
49 case TCP_SRC:
Rob Vaterlausf13323d2013-10-10 13:30:29 -070050 result = tcpSrc;
Andreas Wundsamf89f7822013-09-23 14:49:24 -070051 break;
52 case TCP_DST:
53 result = tcpDst;
54 break;
55 case UDP_SRC:
56 result = tcpSrc;
57 break;
58 case UDP_DST:
59 result = tcpDst;
60 break;
61 case SCTP_SRC:
62 result = tcpSrc;
63 break;
64 case SCTP_DST:
65 result = tcpDst;
66 break;
67 case ICMPV4_TYPE:
68 result = tcpSrc;
69 break;
70 case ICMPV4_CODE:
71 result = tcpDst;
72 break;
73 // NOT SUPPORTED:
74 default:
75 throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
76 }
77 return (F)result;
78 }
Andreas Wundsambc679f72013-08-01 22:13:09 -070079
Andreas Wundsamf89f7822013-09-23 14:49:24 -070080 @SuppressWarnings("unchecked")
81 @Override
82 public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
83 throws UnsupportedOperationException {
84 if (!isPartiallyMasked(field))
85 return null;
86 Object result;
87 switch (field.id) {
88 case IPV4_SRC:
Rob Vaterlausf13323d2013-10-10 13:30:29 -070089 case ARP_SPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -070090 int srcBitMask = (-1) << (32 - getIpv4SrcCidrMaskLen());
91 result = IPv4AddressWithMask.of(ipv4Src, IPv4Address.of(srcBitMask));
92 break;
93 case IPV4_DST:
Rob Vaterlausf13323d2013-10-10 13:30:29 -070094 case ARP_TPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -070095 int dstMaskedBits = Math.min(32, (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT);
96 int dstBitMask = (-1) << (32 - getIpv4DstCidrMaskLen());
Andreas Wundsambc679f72013-08-01 22:13:09 -070097
Andreas Wundsamf89f7822013-09-23 14:49:24 -070098 result = IPv4AddressWithMask.of(ipv4Dst, IPv4Address.of(dstBitMask));
99 break;
100 default:
101 throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
102 }
103 return (Masked<F>)result;
104 }
Andreas Wundsambc679f72013-08-01 22:13:09 -0700105
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700106 @Override
107 public boolean supports(MatchField<?> field) {
108 switch (field.id) {
109 case IN_PORT:
110 case ETH_DST:
111 case ETH_SRC:
112 case ETH_TYPE:
113 case VLAN_VID:
114 case VLAN_PCP:
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700115 case ARP_OP:
116 case ARP_SPA:
117 case ARP_TPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700118 case IP_DSCP:
119 case IP_PROTO:
120 case IPV4_SRC:
121 case IPV4_DST:
122 case TCP_SRC:
123 case TCP_DST:
124 case UDP_SRC:
125 case UDP_DST:
126 case SCTP_SRC:
127 case SCTP_DST:
128 case ICMPV4_TYPE:
129 case ICMPV4_CODE:
130 return true;
131 default:
132 return false;
133 }
134 }
Andreas Wundsambc679f72013-08-01 22:13:09 -0700135
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700136 @Override
137 public boolean supportsMasked(MatchField<?> field) {
138 switch (field.id) {
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700139 case ARP_SPA:
140 case ARP_TPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700141 case IPV4_SRC:
142 case IPV4_DST:
143 return true;
144 default:
145 return false;
146 }
147 }
Andreas Wundsambc679f72013-08-01 22:13:09 -0700148
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700149 @Override
150 public boolean isExact(MatchField<?> field) {
151 switch (field.id) {
152 case IN_PORT:
153 return (this.wildcards & OFPFW_IN_PORT) == 0;
154 case ETH_DST:
155 return (this.wildcards & OFPFW_DL_DST) == 0;
156 case ETH_SRC:
157 return (this.wildcards & OFPFW_DL_SRC) == 0;
158 case ETH_TYPE:
159 return (this.wildcards & OFPFW_DL_TYPE) == 0;
160 case VLAN_VID:
161 return (this.wildcards & OFPFW_DL_VLAN) == 0;
162 case VLAN_PCP:
163 return (this.wildcards & OFPFW_DL_VLAN_PCP) == 0;
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700164 case ARP_OP:
165 return (this.wildcards & OFPFW_NW_PROTO) == 0;
166 case ARP_SPA:
167 return this.getIpv4SrcCidrMaskLen() >= 32;
168 case ARP_TPA:
169 return this.getIpv4DstCidrMaskLen() >= 32;
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700170 case IP_DSCP:
171 return (this.wildcards & OFPFW_NW_TOS) == 0;
172 case IP_PROTO:
173 return (this.wildcards & OFPFW_NW_PROTO) == 0;
174 case IPV4_SRC:
175 return this.getIpv4SrcCidrMaskLen() >= 32;
176 case IPV4_DST:
177 return this.getIpv4DstCidrMaskLen() >= 32;
178 case TCP_SRC:
179 return (this.wildcards & OFPFW_TP_SRC) == 0;
180 case TCP_DST:
181 return (this.wildcards & OFPFW_TP_DST) == 0;
182 case UDP_SRC:
183 return (this.wildcards & OFPFW_TP_SRC) == 0;
184 case UDP_DST:
185 return (this.wildcards & OFPFW_TP_DST) == 0;
186 case SCTP_SRC:
187 return (this.wildcards & OFPFW_TP_SRC) == 0;
188 case SCTP_DST:
189 return (this.wildcards & OFPFW_TP_DST) == 0;
190 case ICMPV4_TYPE:
191 return (this.wildcards & OFPFW_TP_SRC) == 0;
192 case ICMPV4_CODE:
193 return (this.wildcards & OFPFW_TP_DST) == 0;
194 default:
195 throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
196 }
197 }
Andreas Wundsambc679f72013-08-01 22:13:09 -0700198
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700199 /**
200 * Parse this match's wildcard fields and return the number of significant
201 * bits in the IP destination field. NOTE: this returns the number of bits
202 * that are fixed, i.e., like CIDR, not the number of bits that are free
203 * like OpenFlow encodes.
204 *
205 * @return A number between 0 (matches all IPs) and 32 (exact match)
206 */
207 public int getIpv4DstCidrMaskLen() {
208 return Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
209 0);
210 }
Andreas Wundsambc679f72013-08-01 22:13:09 -0700211
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700212 /**
213 * Parse this match's wildcard fields and return the number of significant
214 * bits in the IP destination field. NOTE: this returns the number of bits
215 * that are fixed, i.e., like CIDR, not the number of bits that are free
216 * like OpenFlow encodes.
217 *
218 * @return A number between 0 (matches all IPs) and 32 (exact match)
219 */
220 public int getIpv4SrcCidrMaskLen() {
221 return Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
222 0);
223 }
Andreas Wundsambc679f72013-08-01 22:13:09 -0700224
Andreas Wundsambc679f72013-08-01 22:13:09 -0700225
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700226 @Override
227 public boolean isFullyWildcarded(MatchField<?> field) {
228 switch (field.id) {
229 case IN_PORT:
230 return (this.wildcards & OFPFW_IN_PORT) != 0;
231 case ETH_DST:
232 return (this.wildcards & OFPFW_DL_DST) != 0;
233 case ETH_SRC:
234 return (this.wildcards & OFPFW_DL_SRC) != 0;
235 case ETH_TYPE:
236 return (this.wildcards & OFPFW_DL_TYPE) != 0;
237 case VLAN_VID:
238 return (this.wildcards & OFPFW_DL_VLAN) != 0;
239 case VLAN_PCP:
240 return (this.wildcards & OFPFW_DL_VLAN_PCP) != 0;
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700241 case ARP_OP:
242 return (this.wildcards & OFPFW_NW_PROTO) != 0;
243 case ARP_SPA:
244 return this.getIpv4SrcCidrMaskLen() <= 0;
245 case ARP_TPA:
246 return this.getIpv4DstCidrMaskLen() <= 0;
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700247 case IP_DSCP:
248 return (this.wildcards & OFPFW_NW_TOS) != 0;
249 case IP_PROTO:
250 return (this.wildcards & OFPFW_NW_PROTO) != 0;
251 case TCP_SRC:
252 return (this.wildcards & OFPFW_TP_SRC) != 0;
253 case TCP_DST:
254 return (this.wildcards & OFPFW_TP_DST) != 0;
255 case UDP_SRC:
256 return (this.wildcards & OFPFW_TP_SRC) != 0;
257 case UDP_DST:
258 return (this.wildcards & OFPFW_TP_DST) != 0;
259 case SCTP_SRC:
260 return (this.wildcards & OFPFW_TP_SRC) != 0;
261 case SCTP_DST:
262 return (this.wildcards & OFPFW_TP_DST) != 0;
263 case ICMPV4_TYPE:
264 return (this.wildcards & OFPFW_TP_SRC) != 0;
265 case ICMPV4_CODE:
266 return (this.wildcards & OFPFW_TP_DST) != 0;
267 case IPV4_SRC:
268 return this.getIpv4SrcCidrMaskLen() <= 0;
269 case IPV4_DST:
270 return this.getIpv4DstCidrMaskLen() <= 0;
271 default:
272 throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
273 }
274 }
Andreas Wundsambc679f72013-08-01 22:13:09 -0700275
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700276 @Override
277 public boolean isPartiallyMasked(MatchField<?> field) {
278 switch (field.id) {
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700279 case ARP_SPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700280 case IPV4_SRC:
281 int srcCidrLen = getIpv4SrcCidrMaskLen();
282 return srcCidrLen > 0 && srcCidrLen < 32;
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700283 case ARP_TPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700284 case IPV4_DST:
Rob Vaterlaus553583b2013-10-10 13:40:47 -0700285 int dstCidrLen = getIpv4DstCidrMaskLen();
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700286 return dstCidrLen > 0 && dstCidrLen < 32;
287 default:
288 throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
289 }
290 }
291
292 private final void initWildcards() {
293 if(!wildcardsSet) {
294 //:: if has_parent:
295 wildcards = parentMessage.wildcards;
296 //:: else:
297 wildcards = OFPFW_ALL;
298 //:: #endif
299 wildcardsSet = true;
300 }
301 }
302
303 @Override
304 public <F extends OFValueType<F>> Match.Builder setExact(MatchField<F> field,
305 F value) {
306 initWildcards();
307 Object val = value;
308 switch (field.id) {
309 case ETH_DST:
310 setEthDst((MacAddress) value);
311 wildcards &= ~OFPFW_DL_DST;
312 break;
313 case ETH_SRC:
314 setEthSrc((MacAddress) value);
315 wildcards &= ~OFPFW_DL_SRC;
316 break;
317 case ETH_TYPE:
318 setEthType((EthType) value);
319 wildcards &= ~OFPFW_DL_TYPE;
320 break;
321 case ICMPV4_CODE:
Byungjoon Leeabb41e52014-03-14 11:48:41 +0900322 setTcpDst(TransportPort.of(((ICMPv4Code)value).getCode()));
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700323 wildcards &= ~OFPFW_TP_DST;
324 break;
325 case ICMPV4_TYPE:
Byungjoon Leeabb41e52014-03-14 11:48:41 +0900326 setTcpSrc(TransportPort.of(((ICMPv4Type)value).getType()));
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700327 wildcards &= ~OFPFW_TP_SRC;
328 break;
329 case IN_PORT:
330 setInPort((OFPort) value);
331 wildcards &= ~OFPFW_IN_PORT;
332 break;
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700333 case ARP_OP:
334 setIpProto(IpProtocol.of((short)((ArpOpcode)value).getOpcode()));
335 wildcards &= ~OFPFW_NW_PROTO;
336 break;
337 case ARP_TPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700338 case IPV4_DST:
339 setIpv4Dst((IPv4Address) value);
340 wildcards &= ~OFPFW_NW_DST_MASK;
341 break;
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700342 case ARP_SPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700343 case IPV4_SRC:
344 setIpv4Src((IPv4Address) value);
345 wildcards &= ~OFPFW_NW_SRC_MASK;
346 break;
347 case IP_DSCP:
348 setIpDscp((IpDscp) value);
349 wildcards &= ~OFPFW_NW_TOS;
350 break;
351 case IP_PROTO:
352 setIpProto((IpProtocol) value);
353 wildcards &= ~OFPFW_NW_PROTO;
354 break;
355 case SCTP_DST:
356 setTcpDst((TransportPort) value);
357 wildcards &= ~OFPFW_TP_DST;
358 break;
359 case SCTP_SRC:
360 setTcpSrc((TransportPort) value);
361 wildcards &= ~OFPFW_TP_SRC;
362 break;
363 case TCP_DST:
364 setTcpDst((TransportPort) value);
365 wildcards &= ~OFPFW_TP_DST;
366 break;
367 case TCP_SRC:
368 setTcpSrc((TransportPort) value);
369 wildcards &= ~OFPFW_TP_SRC;
370 break;
371 case UDP_DST:
372 setTcpDst((TransportPort) value);
373 wildcards &= ~OFPFW_TP_DST;
374 break;
375 case UDP_SRC:
376 setTcpSrc((TransportPort) value);
377 wildcards &= ~OFPFW_TP_SRC;
378 break;
379 case VLAN_PCP:
380 setVlanPcp((VlanPcp) value);
381 wildcards &= ~OFPFW_DL_VLAN_PCP;
382 break;
383 case VLAN_VID:
Andreas Wundsam98a18632013-11-05 11:34:24 -0800384 setVlanVid((OFVlanVidMatch) value);
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700385 wildcards &= ~OFPFW_DL_VLAN;
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700386 break;
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700387 default:
388 throw new UnsupportedOperationException(
389 "OFMatch does not support matching on field " + field.getName());
390 }
391 return this;
392 }
393
394 @Override
395 public <F extends OFValueType<F>> Match.Builder setMasked(MatchField<F> field,
396 F value, F mask) {
397 initWildcards();
398 switch (field.id) {
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700399 case ARP_SPA:
400 case ARP_TPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700401 case IPV4_DST:
402 case IPV4_SRC:
403 Object valObj = value;
404 Object masObj = mask;
405 IPv4Address ip = ((IPv4Address)valObj);
406 int maskval = ((IPv4Address)masObj).getInt();
407 if (Integer.bitCount(~maskval + 1) != 1)
408 throw new UnsupportedOperationException("OFMatch only supports CIDR masks for IPv4");
409 int maskLen = 32 - Integer.bitCount(maskval);
410 switch(field.id) {
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700411 case ARP_TPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700412 case IPV4_DST:
413 setIpv4Dst(ip);
414 wildcards = (wildcards &~OFPFW_NW_DST_MASK) | (maskLen << OFPFW_NW_DST_SHIFT);
415 break;
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700416 case ARP_SPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700417 case IPV4_SRC:
418 setIpv4Src(ip);
419 wildcards = (wildcards &~OFPFW_NW_SRC_MASK) | (maskLen << OFPFW_NW_SRC_SHIFT);
420 break;
421 default:
422 // Cannot really get here
423 break;
424 }
425 break;
426 default:
427 throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
428 }
429 return this;
430 }
431
432 @Override
433 public <F extends OFValueType<F>> Match.Builder setMasked(MatchField<F> field, Masked<F> valueWithMask)
434 throws UnsupportedOperationException {
435 return this.setMasked(field, valueWithMask.getValue(), valueWithMask.getMask());
436 }
437
438 @Override
439 public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
440 initWildcards();
441 switch (field.id) {
442 case ETH_DST:
443 setEthDst(MacAddress.NONE);
444 wildcards |= OFPFW_DL_DST;
445 break;
446 case ETH_SRC:
447 setEthSrc(MacAddress.NONE);
448 wildcards |= OFPFW_DL_SRC;
449 break;
450 case ETH_TYPE:
451 setEthType(EthType.NONE);
452 wildcards |= OFPFW_DL_TYPE;
453 break;
454 case ICMPV4_CODE:
455 case TCP_DST:
456 case UDP_DST:
457 case SCTP_DST:
458 setTcpDst(TransportPort.NONE);
459 wildcards |= OFPFW_TP_DST;
460 break;
461 case ICMPV4_TYPE:
462 case TCP_SRC:
463 case UDP_SRC:
464 case SCTP_SRC:
465 setTcpSrc(TransportPort.NONE);
466 wildcards |= OFPFW_TP_SRC;
467 break;
468 case IN_PORT:
Andreas Wundsamad499c92013-09-28 18:56:49 -0700469 setInPort(OFPort.of(0)); // NOTE: not 'NONE' -- that is 0xFF for ports
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700470 wildcards |= OFPFW_IN_PORT;
471 break;
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700472 case ARP_TPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700473 case IPV4_DST:
474 setIpv4Dst(IPv4Address.NONE);
475 wildcards |= OFPFW_NW_DST_MASK;
476 break;
Rob Vaterlausf13323d2013-10-10 13:30:29 -0700477 case ARP_SPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700478 case IPV4_SRC:
479 setIpv4Src(IPv4Address.NONE);
480 wildcards |= OFPFW_NW_SRC_MASK;
481 break;
482 case IP_DSCP:
483 setIpDscp(IpDscp.NONE);
484 wildcards |= OFPFW_NW_TOS;
485 break;
486 case IP_PROTO:
487 setIpProto(IpProtocol.NONE);
488 wildcards |= OFPFW_NW_PROTO;
489 break;
490 case VLAN_PCP:
491 setVlanPcp(VlanPcp.NONE);
492 wildcards |= OFPFW_DL_VLAN_PCP;
493 break;
494 case VLAN_VID:
Andreas Wundsam98a18632013-11-05 11:34:24 -0800495 setVlanVid(OFVlanVidMatch.NONE);
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700496 wildcards |= OFPFW_DL_VLAN;
497 break;
498 default:
499 throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
500 }
501 return this;
502 }