blob: 7b750bb53f5f5e6ce04d4ad7229b9836ad3443b5 [file] [log] [blame]
Andreas Wundsamf89f7822013-09-23 14:49:24 -07001 final public static int OFPFW_ALL = ((1 << 22) - 1);
Andreas Wundsambc679f72013-08-01 22:13:09 -07002
Andreas Wundsamf89f7822013-09-23 14:49:24 -07003 final public static int OFPFW_IN_PORT = 1 << 0; /* Switch input port. */
4 final public static int OFPFW_DL_VLAN = 1 << 1; /* VLAN id. */
5 final public static int OFPFW_DL_SRC = 1 << 2; /* Ethernet source address. */
6 final public static int OFPFW_DL_DST = 1 << 3; /*
7 * Ethernet destination
8 * address.
9 */
10 final public static int OFPFW_DL_TYPE = 1 << 4; /* Ethernet frame type. */
11 final public static int OFPFW_NW_PROTO = 1 << 5; /* IP protocol. */
12 final public static int OFPFW_TP_SRC = 1 << 6; /* TCP/UDP source port. */
13 final public static int OFPFW_TP_DST = 1 << 7; /* TCP/UDP destination port. */
14
15 /*
16 * IP source address wildcard bit count. 0 is exact match, 1 ignores the
17 * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard
18 * the entire field. This is the *opposite* of the usual convention where
19 * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded.
20 */
21 final public static int OFPFW_NW_SRC_SHIFT = 8;
22 final public static int OFPFW_NW_SRC_BITS = 6;
23 final public static int OFPFW_NW_SRC_MASK = ((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT;
24 final public static int OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT;
25
26 /* IP destination address wildcard bit count. Same format as source. */
27 final public static int OFPFW_NW_DST_SHIFT = 14;
28 final public static int OFPFW_NW_DST_BITS = 6;
29 final public static int OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT;
30 final public static int OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT;
31
32 final public static int OFPFW_DL_VLAN_PCP = 1 << 20; /* VLAN priority. */
33 final public static int OFPFW_NW_TOS = 1 << 21; /* IP ToS (DSCP field, 6bits) */
34
35 @SuppressWarnings("unchecked")
Andreas Wundsambc679f72013-08-01 22:13:09 -070036 @Override
37 public <F extends OFValueType<F>> F get(MatchField<F> field)
38 throws UnsupportedOperationException {
Andreas Wundsamf89f7822013-09-23 14:49:24 -070039 if (isFullyWildcarded(field))
40 return null;
41 if (!field.arePrerequisitesOK(this))
42 return null;
43
44 Object result;
45 switch (field.id) {
46 case IN_PORT:
47 result = inPort;
48 break;
49 case ETH_DST:
50 result = ethDst;
51 break;
52 case ETH_SRC:
53 result = ethSrc;
54 break;
55 case ETH_TYPE:
56 result = ethType;
57 break;
58 case VLAN_VID:
59 result = vlanVid;
60 break;
61 case VLAN_PCP:
62 result = vlanPcp;
63 break;
Rob Vaterlaus3ce6fe32013-10-15 13:52:05 -070064 case ARP_OP:
65 result = ArpOpcode.of(ipProto.getIpProtocolNumber());
66 break;
67 case ARP_SPA:
68 result = ipv4Src;
69 break;
70 case ARP_TPA:
71 result = ipv4Dst;
72 break;
Andreas Wundsamf89f7822013-09-23 14:49:24 -070073 case IP_DSCP:
74 result = ipDscp;
75 break;
76 case IP_PROTO:
77 result = ipProto;
78 break;
79 case IPV4_SRC:
Rob Vaterlaus3ce6fe32013-10-15 13:52:05 -070080 result = ipv4Src;
Andreas Wundsamf89f7822013-09-23 14:49:24 -070081 break;
82 case IPV4_DST:
83 result = ipv4Dst;
84 break;
85 case TCP_SRC:
86 result = ipv4Src;
87 break;
88 case TCP_DST:
89 result = tcpDst;
90 break;
91 case UDP_SRC:
92 result = tcpSrc;
93 break;
94 case UDP_DST:
95 result = tcpDst;
96 break;
97 case SCTP_SRC:
98 result = tcpSrc;
99 break;
100 case SCTP_DST:
101 result = tcpDst;
102 break;
103 case ICMPV4_TYPE:
104 result = tcpSrc;
105 break;
106 case ICMPV4_CODE:
107 result = tcpDst;
108 break;
109 // NOT SUPPORTED:
110 default:
111 throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
112 }
113 return (F)result;
Andreas Wundsambc679f72013-08-01 22:13:09 -0700114 }
115
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700116 @SuppressWarnings("unchecked")
Andreas Wundsambc679f72013-08-01 22:13:09 -0700117 @Override
118 public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
119 throws UnsupportedOperationException {
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700120 if (!isPartiallyMasked(field))
121 return null;
122 if (!field.arePrerequisitesOK(this))
123 return null;
124 Object result;
125 switch (field.id) {
Rob Vaterlaus3ce6fe32013-10-15 13:52:05 -0700126 case ARP_SPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700127 case IPV4_SRC:
128 int srcBitMask = (-1) << (32 - getIpv4SrcCidrMaskLen());
129 result = IPv4AddressWithMask.of(ipv4Src, IPv4Address.of(srcBitMask));
130 break;
Rob Vaterlaus3ce6fe32013-10-15 13:52:05 -0700131 case ARP_TPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700132 case IPV4_DST:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700133 int dstBitMask = (-1) << (32 - getIpv4DstCidrMaskLen());
134
135 result = IPv4AddressWithMask.of(ipv4Dst, IPv4Address.of(dstBitMask));
136 break;
137 default:
138 throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
139 }
140 return (Masked<F>)result;
Andreas Wundsambc679f72013-08-01 22:13:09 -0700141 }
142
143 @Override
144 public boolean supports(MatchField<?> field) {
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700145 switch (field.id) {
146 case IN_PORT:
147 case ETH_DST:
148 case ETH_SRC:
149 case ETH_TYPE:
150 case VLAN_VID:
151 case VLAN_PCP:
Rob Vaterlaus3ce6fe32013-10-15 13:52:05 -0700152 case ARP_OP:
153 case ARP_SPA:
154 case ARP_TPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700155 case IP_DSCP:
156 case IP_PROTO:
157 case IPV4_SRC:
158 case IPV4_DST:
159 case TCP_SRC:
160 case TCP_DST:
161 case UDP_SRC:
162 case UDP_DST:
163 case SCTP_SRC:
164 case SCTP_DST:
165 case ICMPV4_TYPE:
166 case ICMPV4_CODE:
167 return true;
168 default:
169 return false;
170 }
Andreas Wundsambc679f72013-08-01 22:13:09 -0700171 }
172
173 @Override
174 public boolean supportsMasked(MatchField<?> field) {
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700175 switch (field.id) {
Rob Vaterlaus3ce6fe32013-10-15 13:52:05 -0700176 case ARP_SPA:
177 case ARP_TPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700178 case IPV4_SRC:
179 case IPV4_DST:
180 return true;
181 default:
182 return false;
183 }
Andreas Wundsambc679f72013-08-01 22:13:09 -0700184 }
185
186 @Override
187 public boolean isExact(MatchField<?> field) {
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700188 if (!field.arePrerequisitesOK(this))
189 return false;
190
191 switch (field.id) {
192 case IN_PORT:
193 return (this.wildcards & OFPFW_IN_PORT) == 0;
194 case ETH_DST:
195 return (this.wildcards & OFPFW_DL_DST) == 0;
196 case ETH_SRC:
197 return (this.wildcards & OFPFW_DL_SRC) == 0;
198 case ETH_TYPE:
199 return (this.wildcards & OFPFW_DL_TYPE) == 0;
200 case VLAN_VID:
201 return (this.wildcards & OFPFW_DL_VLAN) == 0;
202 case VLAN_PCP:
203 return (this.wildcards & OFPFW_DL_VLAN_PCP) == 0;
Rob Vaterlaus3ce6fe32013-10-15 13:52:05 -0700204 case ARP_OP:
205 return (this.wildcards & OFPFW_NW_PROTO) == 0;
206 case ARP_SPA:
207 return this.getIpv4SrcCidrMaskLen() >= 32;
208 case ARP_TPA:
209 return this.getIpv4DstCidrMaskLen() >= 32;
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700210 case IP_DSCP:
211 return (this.wildcards & OFPFW_NW_TOS) == 0;
212 case IP_PROTO:
213 return (this.wildcards & OFPFW_NW_PROTO) == 0;
214 case IPV4_SRC:
215 return this.getIpv4SrcCidrMaskLen() >= 32;
216 case IPV4_DST:
217 return this.getIpv4DstCidrMaskLen() >= 32;
218 case TCP_SRC:
219 return (this.wildcards & OFPFW_TP_SRC) == 0;
220 case TCP_DST:
221 return (this.wildcards & OFPFW_TP_DST) == 0;
222 case UDP_SRC:
223 return (this.wildcards & OFPFW_TP_SRC) == 0;
224 case UDP_DST:
225 return (this.wildcards & OFPFW_TP_DST) == 0;
226 case SCTP_SRC:
227 return (this.wildcards & OFPFW_TP_SRC) == 0;
228 case SCTP_DST:
229 return (this.wildcards & OFPFW_TP_DST) == 0;
230 case ICMPV4_TYPE:
231 return (this.wildcards & OFPFW_TP_SRC) == 0;
232 case ICMPV4_CODE:
233 return (this.wildcards & OFPFW_TP_DST) == 0;
234 default:
235 throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
236 }
Andreas Wundsambc679f72013-08-01 22:13:09 -0700237 }
238
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700239 /**
240 * Parse this match's wildcard fields and return the number of significant
241 * bits in the IP destination field. NOTE: this returns the number of bits
242 * that are fixed, i.e., like CIDR, not the number of bits that are free
243 * like OpenFlow encodes.
244 *
245 * @return A number between 0 (matches all IPs) and 32 (exact match)
246 */
247 public int getIpv4DstCidrMaskLen() {
248 return Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
249 0);
250 }
251
252 /**
253 * Parse this match's wildcard fields and return the number of significant
254 * bits in the IP destination field. NOTE: this returns the number of bits
255 * that are fixed, i.e., like CIDR, not the number of bits that are free
256 * like OpenFlow encodes.
257 *
258 * @return A number between 0 (matches all IPs) and 32 (exact match)
259 */
260 public int getIpv4SrcCidrMaskLen() {
261 return Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
262 0);
263 }
264
265
Andreas Wundsambc679f72013-08-01 22:13:09 -0700266 @Override
267 public boolean isFullyWildcarded(MatchField<?> field) {
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700268 if (!field.arePrerequisitesOK(this))
269 return true;
270
271 switch (field.id) {
272 case IN_PORT:
273 return (this.wildcards & OFPFW_IN_PORT) != 0;
274 case ETH_DST:
275 return (this.wildcards & OFPFW_DL_DST) != 0;
276 case ETH_SRC:
277 return (this.wildcards & OFPFW_DL_SRC) != 0;
278 case ETH_TYPE:
279 return (this.wildcards & OFPFW_DL_TYPE) != 0;
280 case VLAN_VID:
281 return (this.wildcards & OFPFW_DL_VLAN) != 0;
282 case VLAN_PCP:
283 return (this.wildcards & OFPFW_DL_VLAN_PCP) != 0;
Rob Vaterlaus3ce6fe32013-10-15 13:52:05 -0700284 case ARP_OP:
285 return (this.wildcards & OFPFW_NW_PROTO) != 0;
286 case ARP_SPA:
287 return this.getIpv4SrcCidrMaskLen() <= 0;
288 case ARP_TPA:
289 return this.getIpv4DstCidrMaskLen() <= 0;
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700290 case IP_DSCP:
291 return (this.wildcards & OFPFW_NW_TOS) != 0;
292 case IP_PROTO:
293 return (this.wildcards & OFPFW_NW_PROTO) != 0;
294 case TCP_SRC:
295 return (this.wildcards & OFPFW_TP_SRC) != 0;
296 case TCP_DST:
297 return (this.wildcards & OFPFW_TP_DST) != 0;
298 case UDP_SRC:
299 return (this.wildcards & OFPFW_TP_SRC) != 0;
300 case UDP_DST:
301 return (this.wildcards & OFPFW_TP_DST) != 0;
302 case SCTP_SRC:
303 return (this.wildcards & OFPFW_TP_SRC) != 0;
304 case SCTP_DST:
305 return (this.wildcards & OFPFW_TP_DST) != 0;
306 case ICMPV4_TYPE:
307 return (this.wildcards & OFPFW_TP_SRC) != 0;
308 case ICMPV4_CODE:
309 return (this.wildcards & OFPFW_TP_DST) != 0;
310 case IPV4_SRC:
311 return this.getIpv4SrcCidrMaskLen() <= 0;
312 case IPV4_DST:
313 return this.getIpv4DstCidrMaskLen() <= 0;
314 default:
315 throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
316 }
Andreas Wundsambc679f72013-08-01 22:13:09 -0700317 }
318
319 @Override
320 public boolean isPartiallyMasked(MatchField<?> field) {
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700321 if (!field.arePrerequisitesOK(this))
322 return false;
323
324 switch (field.id) {
Rob Vaterlaus3ce6fe32013-10-15 13:52:05 -0700325 case ARP_SPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700326 case IPV4_SRC:
327 int srcCidrLen = getIpv4SrcCidrMaskLen();
328 return srcCidrLen > 0 && srcCidrLen < 32;
Rob Vaterlaus3ce6fe32013-10-15 13:52:05 -0700329 case ARP_TPA:
Andreas Wundsamf89f7822013-09-23 14:49:24 -0700330 case IPV4_DST:
331 int dstCidrLen = getIpv4SrcCidrMaskLen();
332 return dstCidrLen > 0 && dstCidrLen < 32;
333 default:
334 throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
335 }
Andreas Wundsambc679f72013-08-01 22:13:09 -0700336 }
Rob Vaterlaus934b4ad2013-11-12 10:08:59 -0800337
338 @Override
339 public Iterable<MatchField<?>> getMatchFields() {
340 ImmutableList.Builder<MatchField<?>> builder = ImmutableList.builder();
341 if ((wildcards & OFPFW_IN_PORT) == 0)
342 builder.add(MatchField.IN_PORT);
343 if ((wildcards & OFPFW_DL_VLAN) == 0)
344 builder.add(MatchField.VLAN_VID);
345 if ((wildcards & OFPFW_DL_SRC) == 0)
346 builder.add(MatchField.ETH_SRC);
347 if ((wildcards & OFPFW_DL_DST) == 0)
348 builder.add(MatchField.ETH_DST);
349 if ((wildcards & OFPFW_DL_TYPE) == 0)
350 builder.add(MatchField.ETH_TYPE);
351 if ((wildcards & OFPFW_NW_PROTO) == 0) {
352 if (ethType == EthType.ARP) {
353 builder.add(MatchField.ARP_OP);
354 } else if (ethType == EthType.IPv4) {
355 builder.add(MatchField.IP_PROTO);
356 } else {
357 throw new UnsupportedOperationException(
358 "Unsupported Ethertype for matching on network protocol " + ethType);
359 }
360 }
361 if ((wildcards & OFPFW_TP_SRC) == 0) {
362 if (ipProto == IpProtocol.UDP) {
363 builder.add(MatchField.UDP_SRC);
364 } else if (ipProto == IpProtocol.TCP) {
365 builder.add(MatchField.TCP_SRC);
366 } else if (ipProto == IpProtocol.SCTP) {
367 builder.add(MatchField.SCTP_SRC);
368 } else {
369 throw new UnsupportedOperationException(
370 "Unsupported IP protocol for matching on source port " + ipProto);
371 }
372 }
373 if ((wildcards & OFPFW_TP_DST) == 0) {
374 if (ipProto == IpProtocol.UDP) {
375 builder.add(MatchField.UDP_DST);
376 } else if (ipProto == IpProtocol.TCP) {
377 builder.add(MatchField.TCP_DST);
378 } else if (ipProto == IpProtocol.SCTP) {
379 builder.add(MatchField.SCTP_DST);
380 } else {
381 throw new UnsupportedOperationException(
382 "Unsupported IP protocol for matching on destination port " + ipProto);
383 }
384 }
385 if (((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT) < 32) {
386 if (ethType == EthType.ARP) {
387 builder.add(MatchField.ARP_SPA);
388 } else if (ethType == EthType.IPv4) {
389 builder.add(MatchField.IPV4_SRC);
390 } else {
391 throw new UnsupportedOperationException(
392 "Unsupported Ethertype for matching on source IP " + ethType);
393 }
394 }
395 if (((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT) < 32) {
396 if (ethType == EthType.ARP) {
397 builder.add(MatchField.ARP_TPA);
398 } else if (ethType == EthType.IPv4) {
399 builder.add(MatchField.IPV4_DST);
400 } else {
401 throw new UnsupportedOperationException(
402 "Unsupported Ethertype for matching on destination IP " + ethType);
403 }
404 }
405 if ((wildcards & OFPFW_DL_VLAN_PCP) == 0)
406 builder.add(MatchField.VLAN_PCP);
407 if ((wildcards & OFPFW_NW_TOS) == 0)
408 builder.add(MatchField.IP_DSCP);
409 return builder.build();
410 }