]>
Commit | Line | Data |
---|---|---|
064af421 | 1 | /* |
8368c090 | 2 | * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. |
064af421 | 3 | * |
a14bc59f BP |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
064af421 | 7 | * |
a14bc59f BP |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
064af421 BP |
15 | */ |
16 | #include <config.h> | |
17 | #include <sys/types.h> | |
18 | #include "flow.h" | |
db7f8281 | 19 | #include <assert.h> |
d31f1109 | 20 | #include <errno.h> |
064af421 BP |
21 | #include <inttypes.h> |
22 | #include <netinet/in.h> | |
d31f1109 JP |
23 | #include <netinet/icmp6.h> |
24 | #include <netinet/ip6.h> | |
064af421 BP |
25 | #include <stdlib.h> |
26 | #include <string.h> | |
10a24935 | 27 | #include "byte-order.h" |
064af421 | 28 | #include "coverage.h" |
c97fb132 | 29 | #include "dpif.h" |
064af421 BP |
30 | #include "dynamic-string.h" |
31 | #include "hash.h" | |
32 | #include "ofpbuf.h" | |
33 | #include "openflow/openflow.h" | |
34 | #include "openvswitch/datapath-protocol.h" | |
35 | #include "packets.h" | |
176aaa65 | 36 | #include "unaligned.h" |
5136ce49 | 37 | #include "vlog.h" |
064af421 | 38 | |
d98e6007 | 39 | VLOG_DEFINE_THIS_MODULE(flow); |
064af421 | 40 | |
d76f09ea BP |
41 | COVERAGE_DEFINE(flow_extract); |
42 | ||
a26ef517 JP |
43 | static struct arp_eth_header * |
44 | pull_arp(struct ofpbuf *packet) | |
45 | { | |
46 | return ofpbuf_try_pull(packet, ARP_ETH_HEADER_LEN); | |
47 | } | |
48 | ||
064af421 BP |
49 | static struct ip_header * |
50 | pull_ip(struct ofpbuf *packet) | |
51 | { | |
52 | if (packet->size >= IP_HEADER_LEN) { | |
53 | struct ip_header *ip = packet->data; | |
54 | int ip_len = IP_IHL(ip->ip_ihl_ver) * 4; | |
55 | if (ip_len >= IP_HEADER_LEN && packet->size >= ip_len) { | |
56 | return ofpbuf_pull(packet, ip_len); | |
57 | } | |
58 | } | |
59 | return NULL; | |
60 | } | |
61 | ||
62 | static struct tcp_header * | |
d295e8e9 | 63 | pull_tcp(struct ofpbuf *packet) |
064af421 BP |
64 | { |
65 | if (packet->size >= TCP_HEADER_LEN) { | |
66 | struct tcp_header *tcp = packet->data; | |
67 | int tcp_len = TCP_OFFSET(tcp->tcp_ctl) * 4; | |
68 | if (tcp_len >= TCP_HEADER_LEN && packet->size >= tcp_len) { | |
69 | return ofpbuf_pull(packet, tcp_len); | |
70 | } | |
71 | } | |
72 | return NULL; | |
73 | } | |
74 | ||
75 | static struct udp_header * | |
d295e8e9 | 76 | pull_udp(struct ofpbuf *packet) |
064af421 BP |
77 | { |
78 | return ofpbuf_try_pull(packet, UDP_HEADER_LEN); | |
79 | } | |
80 | ||
81 | static struct icmp_header * | |
d295e8e9 | 82 | pull_icmp(struct ofpbuf *packet) |
064af421 BP |
83 | { |
84 | return ofpbuf_try_pull(packet, ICMP_HEADER_LEN); | |
85 | } | |
86 | ||
d31f1109 JP |
87 | static struct icmp6_hdr * |
88 | pull_icmpv6(struct ofpbuf *packet) | |
89 | { | |
90 | return ofpbuf_try_pull(packet, sizeof(struct icmp6_hdr)); | |
91 | } | |
92 | ||
50f06e16 | 93 | static void |
ae412e7d | 94 | parse_vlan(struct ofpbuf *b, struct flow *flow) |
064af421 | 95 | { |
50f06e16 | 96 | struct qtag_prefix { |
0b3e77bb BP |
97 | ovs_be16 eth_type; /* ETH_TYPE_VLAN */ |
98 | ovs_be16 tci; | |
50f06e16 BP |
99 | }; |
100 | ||
0b3e77bb | 101 | if (b->size >= sizeof(struct qtag_prefix) + sizeof(ovs_be16)) { |
50f06e16 | 102 | struct qtag_prefix *qp = ofpbuf_pull(b, sizeof *qp); |
66642cb4 | 103 | flow->vlan_tci = qp->tci | htons(VLAN_CFI); |
50f06e16 | 104 | } |
064af421 BP |
105 | } |
106 | ||
0b3e77bb | 107 | static ovs_be16 |
50f06e16 | 108 | parse_ethertype(struct ofpbuf *b) |
064af421 | 109 | { |
50f06e16 | 110 | struct llc_snap_header *llc; |
0b3e77bb | 111 | ovs_be16 proto; |
50f06e16 | 112 | |
0b3e77bb | 113 | proto = *(ovs_be16 *) ofpbuf_pull(b, sizeof proto); |
36956a7d | 114 | if (ntohs(proto) >= ETH_TYPE_MIN) { |
50f06e16 BP |
115 | return proto; |
116 | } | |
117 | ||
118 | if (b->size < sizeof *llc) { | |
36956a7d | 119 | return htons(FLOW_DL_TYPE_NONE); |
50f06e16 BP |
120 | } |
121 | ||
122 | llc = b->data; | |
123 | if (llc->llc.llc_dsap != LLC_DSAP_SNAP | |
124 | || llc->llc.llc_ssap != LLC_SSAP_SNAP | |
125 | || llc->llc.llc_cntl != LLC_CNTL_SNAP | |
126 | || memcmp(llc->snap.snap_org, SNAP_ORG_ETHERNET, | |
127 | sizeof llc->snap.snap_org)) { | |
36956a7d | 128 | return htons(FLOW_DL_TYPE_NONE); |
50f06e16 BP |
129 | } |
130 | ||
131 | ofpbuf_pull(b, sizeof *llc); | |
132 | return llc->snap.snap_type; | |
064af421 BP |
133 | } |
134 | ||
d31f1109 JP |
135 | static int |
136 | parse_ipv6(struct ofpbuf *packet, struct flow *flow) | |
137 | { | |
88366484 | 138 | const struct ip6_hdr *nh; |
d31f1109 JP |
139 | ovs_be32 tc_flow; |
140 | int nexthdr; | |
141 | ||
88366484 JG |
142 | nh = ofpbuf_try_pull(packet, sizeof *nh); |
143 | if (!nh) { | |
144 | return EINVAL; | |
d31f1109 JP |
145 | } |
146 | ||
d31f1109 | 147 | nexthdr = nh->ip6_nxt; |
d31f1109 JP |
148 | |
149 | flow->ipv6_src = nh->ip6_src; | |
150 | flow->ipv6_dst = nh->ip6_dst; | |
151 | ||
152 | tc_flow = get_unaligned_be32(&nh->ip6_flow); | |
153 | flow->nw_tos = (ntohl(tc_flow) >> 4) & IP_DSCP_MASK; | |
154 | flow->nw_proto = IPPROTO_NONE; | |
155 | ||
d31f1109 JP |
156 | while (1) { |
157 | if ((nexthdr != IPPROTO_HOPOPTS) | |
158 | && (nexthdr != IPPROTO_ROUTING) | |
159 | && (nexthdr != IPPROTO_DSTOPTS) | |
160 | && (nexthdr != IPPROTO_AH) | |
161 | && (nexthdr != IPPROTO_FRAGMENT)) { | |
162 | /* It's either a terminal header (e.g., TCP, UDP) or one we | |
163 | * don't understand. In either case, we're done with the | |
164 | * packet, so use it to fill in 'nw_proto'. */ | |
165 | break; | |
166 | } | |
167 | ||
168 | /* We only verify that at least 8 bytes of the next header are | |
169 | * available, but many of these headers are longer. Ensure that | |
170 | * accesses within the extension header are within those first 8 | |
88366484 | 171 | * bytes. All extension headers are required to be at least 8 |
d31f1109 | 172 | * bytes. */ |
88366484 JG |
173 | if (packet->size < 8) { |
174 | return EINVAL; | |
d31f1109 JP |
175 | } |
176 | ||
177 | if ((nexthdr == IPPROTO_HOPOPTS) | |
178 | || (nexthdr == IPPROTO_ROUTING) | |
179 | || (nexthdr == IPPROTO_DSTOPTS)) { | |
180 | /* These headers, while different, have the fields we care about | |
181 | * in the same location and with the same interpretation. */ | |
88366484 | 182 | const struct ip6_ext *ext_hdr = (struct ip6_ext *)packet->data; |
d31f1109 | 183 | nexthdr = ext_hdr->ip6e_nxt; |
88366484 JG |
184 | if (!ofpbuf_try_pull(packet, (ext_hdr->ip6e_len + 1) * 8)) { |
185 | return EINVAL; | |
186 | } | |
d31f1109 JP |
187 | } else if (nexthdr == IPPROTO_AH) { |
188 | /* A standard AH definition isn't available, but the fields | |
189 | * we care about are in the same location as the generic | |
190 | * option header--only the header length is calculated | |
191 | * differently. */ | |
88366484 | 192 | const struct ip6_ext *ext_hdr = (struct ip6_ext *)packet->data; |
d31f1109 | 193 | nexthdr = ext_hdr->ip6e_nxt; |
88366484 JG |
194 | if (!ofpbuf_try_pull(packet, (ext_hdr->ip6e_len + 2) * 4)) { |
195 | return EINVAL; | |
196 | } | |
d31f1109 | 197 | } else if (nexthdr == IPPROTO_FRAGMENT) { |
88366484 | 198 | const struct ip6_frag *frag_hdr = (struct ip6_frag *)packet->data; |
d31f1109 JP |
199 | |
200 | nexthdr = frag_hdr->ip6f_nxt; | |
88366484 JG |
201 | if (!ofpbuf_try_pull(packet, sizeof *frag_hdr)) { |
202 | return EINVAL; | |
203 | } | |
d31f1109 JP |
204 | |
205 | /* We only process the first fragment. */ | |
206 | if ((frag_hdr->ip6f_offlg & IP6F_OFF_MASK) != htons(0)) { | |
207 | nexthdr = IPPROTO_FRAGMENT; | |
208 | break; | |
209 | } | |
210 | } | |
211 | } | |
212 | ||
d31f1109 | 213 | flow->nw_proto = nexthdr; |
88366484 | 214 | return 0; |
d31f1109 JP |
215 | } |
216 | ||
88366484 JG |
217 | static void |
218 | parse_tcp(struct ofpbuf *packet, struct ofpbuf *b, struct flow *flow) | |
219 | { | |
220 | const struct tcp_header *tcp = pull_tcp(b); | |
221 | if (tcp) { | |
222 | flow->tp_src = tcp->tcp_src; | |
223 | flow->tp_dst = tcp->tcp_dst; | |
224 | packet->l7 = b->data; | |
225 | } | |
226 | } | |
227 | ||
228 | static void | |
229 | parse_udp(struct ofpbuf *packet, struct ofpbuf *b, struct flow *flow) | |
230 | { | |
231 | const struct udp_header *udp = pull_udp(b); | |
232 | if (udp) { | |
233 | flow->tp_src = udp->udp_src; | |
234 | flow->tp_dst = udp->udp_dst; | |
235 | packet->l7 = b->data; | |
236 | } | |
237 | } | |
685a51a5 JP |
238 | |
239 | static bool | |
88366484 | 240 | parse_icmpv6(struct ofpbuf *b, struct flow *flow) |
685a51a5 JP |
241 | { |
242 | const struct icmp6_hdr *icmp = pull_icmpv6(b); | |
243 | ||
244 | if (!icmp) { | |
245 | return false; | |
246 | } | |
247 | ||
248 | /* The ICMPv6 type and code fields use the 16-bit transport port | |
249 | * fields, so we need to store them in 16-bit network byte order. */ | |
250 | flow->icmp_type = htons(icmp->icmp6_type); | |
251 | flow->icmp_code = htons(icmp->icmp6_code); | |
252 | ||
88366484 JG |
253 | if (icmp->icmp6_code == 0 && |
254 | (icmp->icmp6_type == ND_NEIGHBOR_SOLICIT || | |
255 | icmp->icmp6_type == ND_NEIGHBOR_ADVERT)) { | |
256 | const struct in6_addr *nd_target; | |
685a51a5 | 257 | |
88366484 JG |
258 | nd_target = ofpbuf_try_pull(b, sizeof *nd_target); |
259 | if (!nd_target) { | |
685a51a5 JP |
260 | return false; |
261 | } | |
88366484 | 262 | flow->nd_target = *nd_target; |
685a51a5 | 263 | |
88366484 | 264 | while (b->size >= 8) { |
685a51a5 JP |
265 | /* The minimum size of an option is 8 bytes, which also is |
266 | * the size of Ethernet link-layer options. */ | |
88366484 JG |
267 | const struct nd_opt_hdr *nd_opt = b->data; |
268 | int opt_len = nd_opt->nd_opt_len * 8; | |
269 | ||
270 | if (!opt_len || opt_len > b->size) { | |
685a51a5 JP |
271 | goto invalid; |
272 | } | |
685a51a5 JP |
273 | |
274 | /* Store the link layer address if the appropriate option is | |
275 | * provided. It is considered an error if the same link | |
276 | * layer option is specified twice. */ | |
277 | if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LINKADDR | |
278 | && opt_len == 8) { | |
279 | if (eth_addr_is_zero(flow->arp_sha)) { | |
88366484 | 280 | memcpy(flow->arp_sha, nd_opt + 1, ETH_ADDR_LEN); |
685a51a5 JP |
281 | } else { |
282 | goto invalid; | |
283 | } | |
284 | } else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LINKADDR | |
285 | && opt_len == 8) { | |
286 | if (eth_addr_is_zero(flow->arp_tha)) { | |
88366484 | 287 | memcpy(flow->arp_tha, nd_opt + 1, ETH_ADDR_LEN); |
685a51a5 JP |
288 | } else { |
289 | goto invalid; | |
290 | } | |
291 | } | |
292 | ||
88366484 | 293 | if (!ofpbuf_try_pull(b, opt_len)) { |
685a51a5 JP |
294 | goto invalid; |
295 | } | |
685a51a5 JP |
296 | } |
297 | } | |
298 | ||
299 | return true; | |
300 | ||
301 | invalid: | |
88366484 JG |
302 | memset(&flow->nd_target, 0, sizeof(flow->nd_target)); |
303 | memset(flow->arp_sha, 0, sizeof(flow->arp_sha)); | |
304 | memset(flow->arp_tha, 0, sizeof(flow->arp_tha)); | |
685a51a5 JP |
305 | |
306 | return false; | |
307 | ||
308 | } | |
309 | ||
abe529af | 310 | /* Initializes 'flow' members from 'packet', 'tun_id', and 'ofp_in_port'. |
0b3e77bb | 311 | * Initializes 'packet' header pointers as follows: |
ca78c6b6 BP |
312 | * |
313 | * - packet->l2 to the start of the Ethernet header. | |
314 | * | |
315 | * - packet->l3 to just past the Ethernet header, or just past the | |
316 | * vlan_header if one is present, to the first byte of the payload of the | |
317 | * Ethernet frame. | |
318 | * | |
319 | * - packet->l4 to just past the IPv4 header, if one is present and has a | |
320 | * correct length, and otherwise NULL. | |
321 | * | |
322 | * - packet->l7 to just past the TCP or UDP or ICMP header, if one is | |
323 | * present and has a correct length, and otherwise NULL. | |
324 | */ | |
064af421 | 325 | int |
abe529af | 326 | flow_extract(struct ofpbuf *packet, ovs_be64 tun_id, uint16_t ofp_in_port, |
ae412e7d | 327 | struct flow *flow) |
064af421 BP |
328 | { |
329 | struct ofpbuf b = *packet; | |
330 | struct eth_header *eth; | |
331 | int retval = 0; | |
332 | ||
333 | COVERAGE_INC(flow_extract); | |
334 | ||
335 | memset(flow, 0, sizeof *flow); | |
659586ef | 336 | flow->tun_id = tun_id; |
abe529af | 337 | flow->in_port = ofp_in_port; |
064af421 BP |
338 | |
339 | packet->l2 = b.data; | |
340 | packet->l3 = NULL; | |
341 | packet->l4 = NULL; | |
342 | packet->l7 = NULL; | |
343 | ||
50f06e16 BP |
344 | if (b.size < sizeof *eth) { |
345 | return 0; | |
346 | } | |
064af421 | 347 | |
50f06e16 BP |
348 | /* Link layer. */ |
349 | eth = b.data; | |
350 | memcpy(flow->dl_src, eth->eth_src, ETH_ADDR_LEN); | |
351 | memcpy(flow->dl_dst, eth->eth_dst, ETH_ADDR_LEN); | |
352 | ||
66642cb4 | 353 | /* dl_type, vlan_tci. */ |
50f06e16 BP |
354 | ofpbuf_pull(&b, ETH_ADDR_LEN * 2); |
355 | if (eth->eth_type == htons(ETH_TYPE_VLAN)) { | |
356 | parse_vlan(&b, flow); | |
357 | } | |
358 | flow->dl_type = parse_ethertype(&b); | |
359 | ||
360 | /* Network layer. */ | |
361 | packet->l3 = b.data; | |
362 | if (flow->dl_type == htons(ETH_TYPE_IP)) { | |
363 | const struct ip_header *nh = pull_ip(&b); | |
364 | if (nh) { | |
9ea5d2d5 BP |
365 | flow->nw_src = get_unaligned_be32(&nh->ip_src); |
366 | flow->nw_dst = get_unaligned_be32(&nh->ip_dst); | |
50f06e16 BP |
367 | flow->nw_tos = nh->ip_tos & IP_DSCP_MASK; |
368 | flow->nw_proto = nh->ip_proto; | |
369 | packet->l4 = b.data; | |
370 | if (!IP_IS_FRAGMENT(nh->ip_frag_off)) { | |
6767a2cc | 371 | if (flow->nw_proto == IPPROTO_TCP) { |
88366484 | 372 | parse_tcp(packet, &b, flow); |
6767a2cc | 373 | } else if (flow->nw_proto == IPPROTO_UDP) { |
88366484 | 374 | parse_udp(packet, &b, flow); |
6767a2cc | 375 | } else if (flow->nw_proto == IPPROTO_ICMP) { |
50f06e16 BP |
376 | const struct icmp_header *icmp = pull_icmp(&b); |
377 | if (icmp) { | |
378 | flow->icmp_type = htons(icmp->icmp_type); | |
379 | flow->icmp_code = htons(icmp->icmp_code); | |
380 | packet->l7 = b.data; | |
064af421 | 381 | } |
064af421 | 382 | } |
50f06e16 BP |
383 | } else { |
384 | retval = 1; | |
385 | } | |
386 | } | |
d31f1109 | 387 | } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { |
d31f1109 | 388 | |
88366484 JG |
389 | retval = parse_ipv6(&b, flow); |
390 | if (retval) { | |
d31f1109 JP |
391 | return 0; |
392 | } | |
393 | ||
88366484 JG |
394 | packet->l4 = b.data; |
395 | if (flow->nw_proto == IPPROTO_TCP) { | |
396 | parse_tcp(packet, &b, flow); | |
397 | } else if (flow->nw_proto == IPPROTO_UDP) { | |
398 | parse_udp(packet, &b, flow); | |
399 | } else if (flow->nw_proto == IPPROTO_ICMPV6) { | |
400 | if (parse_icmpv6(&b, flow)) { | |
401 | packet->l7 = b.data; | |
d31f1109 JP |
402 | } |
403 | } | |
50f06e16 BP |
404 | } else if (flow->dl_type == htons(ETH_TYPE_ARP)) { |
405 | const struct arp_eth_header *arp = pull_arp(&b); | |
406 | if (arp && arp->ar_hrd == htons(1) | |
d295e8e9 | 407 | && arp->ar_pro == htons(ETH_TYPE_IP) |
50f06e16 BP |
408 | && arp->ar_hln == ETH_ADDR_LEN |
409 | && arp->ar_pln == 4) { | |
410 | /* We only match on the lower 8 bits of the opcode. */ | |
411 | if (ntohs(arp->ar_op) <= 0xff) { | |
412 | flow->nw_proto = ntohs(arp->ar_op); | |
064af421 | 413 | } |
a26ef517 | 414 | |
d295e8e9 | 415 | if ((flow->nw_proto == ARP_OP_REQUEST) |
50f06e16 BP |
416 | || (flow->nw_proto == ARP_OP_REPLY)) { |
417 | flow->nw_src = arp->ar_spa; | |
418 | flow->nw_dst = arp->ar_tpa; | |
bad68a99 JP |
419 | memcpy(flow->arp_sha, arp->ar_sha, ETH_ADDR_LEN); |
420 | memcpy(flow->arp_tha, arp->ar_tha, ETH_ADDR_LEN); | |
a26ef517 | 421 | } |
064af421 BP |
422 | } |
423 | } | |
d31f1109 | 424 | |
064af421 BP |
425 | return retval; |
426 | } | |
427 | ||
428 | /* Extracts the flow stats for a packet. The 'flow' and 'packet' | |
429 | * arguments must have been initialized through a call to flow_extract(). | |
430 | */ | |
431 | void | |
ae412e7d | 432 | flow_extract_stats(const struct flow *flow, struct ofpbuf *packet, |
c97fb132 | 433 | struct dpif_flow_stats *stats) |
064af421 | 434 | { |
c97fb132 | 435 | memset(stats, 0, sizeof(*stats)); |
064af421 BP |
436 | |
437 | if ((flow->dl_type == htons(ETH_TYPE_IP)) && packet->l4) { | |
6767a2cc | 438 | if ((flow->nw_proto == IPPROTO_TCP) && packet->l7) { |
064af421 BP |
439 | struct tcp_header *tcp = packet->l4; |
440 | stats->tcp_flags = TCP_FLAGS(tcp->tcp_ctl); | |
441 | } | |
442 | } | |
443 | ||
444 | stats->n_bytes = packet->size; | |
445 | stats->n_packets = 1; | |
446 | } | |
447 | ||
064af421 | 448 | char * |
ae412e7d | 449 | flow_to_string(const struct flow *flow) |
064af421 BP |
450 | { |
451 | struct ds ds = DS_EMPTY_INITIALIZER; | |
452 | flow_format(&ds, flow); | |
453 | return ds_cstr(&ds); | |
454 | } | |
455 | ||
456 | void | |
ae412e7d | 457 | flow_format(struct ds *ds, const struct flow *flow) |
064af421 | 458 | { |
b9298d3f | 459 | ds_put_format(ds, "tunnel%#"PRIx64":in_port%04"PRIx16":tci(", |
19997cee | 460 | ntohll(flow->tun_id), flow->in_port); |
66642cb4 BP |
461 | if (flow->vlan_tci) { |
462 | ds_put_format(ds, "vlan%"PRIu16",pcp%d", | |
463 | vlan_tci_to_vid(flow->vlan_tci), | |
464 | vlan_tci_to_pcp(flow->vlan_tci)); | |
465 | } else { | |
466 | ds_put_char(ds, '0'); | |
467 | } | |
468 | ds_put_format(ds, ") mac"ETH_ADDR_FMT"->"ETH_ADDR_FMT | |
d31f1109 | 469 | " type%04"PRIx16, |
659586ef JG |
470 | ETH_ADDR_ARGS(flow->dl_src), |
471 | ETH_ADDR_ARGS(flow->dl_dst), | |
d31f1109 JP |
472 | ntohs(flow->dl_type)); |
473 | ||
474 | if (flow->dl_type == htons(ETH_TYPE_IPV6)) { | |
475 | ds_put_format(ds, " proto%"PRIu8" tos%"PRIu8" ipv6", | |
476 | flow->nw_proto, flow->nw_tos); | |
477 | print_ipv6_addr(ds, &flow->ipv6_src); | |
478 | ds_put_cstr(ds, "->"); | |
479 | print_ipv6_addr(ds, &flow->ipv6_dst); | |
480 | ||
481 | } else { | |
482 | ds_put_format(ds, " proto%"PRIu8 | |
483 | " tos%"PRIu8 | |
484 | " ip"IP_FMT"->"IP_FMT, | |
485 | flow->nw_proto, | |
486 | flow->nw_tos, | |
487 | IP_ARGS(&flow->nw_src), | |
488 | IP_ARGS(&flow->nw_dst)); | |
489 | } | |
bad68a99 JP |
490 | if (flow->tp_src || flow->tp_dst) { |
491 | ds_put_format(ds, " port%"PRIu16"->%"PRIu16, | |
492 | ntohs(flow->tp_src), ntohs(flow->tp_dst)); | |
493 | } | |
494 | if (!eth_addr_is_zero(flow->arp_sha) || !eth_addr_is_zero(flow->arp_tha)) { | |
495 | ds_put_format(ds, " arp_ha"ETH_ADDR_FMT"->"ETH_ADDR_FMT, | |
496 | ETH_ADDR_ARGS(flow->arp_sha), | |
497 | ETH_ADDR_ARGS(flow->arp_tha)); | |
498 | } | |
064af421 BP |
499 | } |
500 | ||
501 | void | |
ae412e7d | 502 | flow_print(FILE *stream, const struct flow *flow) |
064af421 BP |
503 | { |
504 | char *s = flow_to_string(flow); | |
505 | fputs(s, stream); | |
506 | free(s); | |
507 | } | |
54363004 BP |
508 | \f |
509 | /* flow_wildcards functions. */ | |
510 | ||
d8ae4d67 | 511 | /* Initializes 'wc' as a set of wildcards that matches every packet. */ |
54363004 | 512 | void |
d8ae4d67 | 513 | flow_wildcards_init_catchall(struct flow_wildcards *wc) |
54363004 | 514 | { |
d8ae4d67 | 515 | wc->wildcards = FWW_ALL; |
8368c090 | 516 | wc->tun_id_mask = htonll(0); |
d8ae4d67 BP |
517 | wc->nw_src_mask = htonl(0); |
518 | wc->nw_dst_mask = htonl(0); | |
d31f1109 JP |
519 | wc->ipv6_src_mask = in6addr_any; |
520 | wc->ipv6_dst_mask = in6addr_any; | |
b6c9e612 | 521 | memset(wc->reg_masks, 0, sizeof wc->reg_masks); |
66642cb4 | 522 | wc->vlan_tci_mask = htons(0); |
29b639ed | 523 | wc->zero = 0; |
54363004 BP |
524 | } |
525 | ||
494e43a5 BP |
526 | /* Initializes 'wc' as an exact-match set of wildcards; that is, 'wc' does not |
527 | * wildcard any bits or fields. */ | |
528 | void | |
529 | flow_wildcards_init_exact(struct flow_wildcards *wc) | |
530 | { | |
b6c9e612 | 531 | wc->wildcards = 0; |
8368c090 | 532 | wc->tun_id_mask = htonll(UINT64_MAX); |
b6c9e612 BP |
533 | wc->nw_src_mask = htonl(UINT32_MAX); |
534 | wc->nw_dst_mask = htonl(UINT32_MAX); | |
d31f1109 JP |
535 | wc->ipv6_src_mask = in6addr_exact; |
536 | wc->ipv6_dst_mask = in6addr_exact; | |
b6c9e612 | 537 | memset(wc->reg_masks, 0xff, sizeof wc->reg_masks); |
66642cb4 | 538 | wc->vlan_tci_mask = htons(UINT16_MAX); |
29b639ed | 539 | wc->zero = 0; |
494e43a5 BP |
540 | } |
541 | ||
00561f41 BP |
542 | /* Returns true if 'wc' is exact-match, false if 'wc' wildcards any bits or |
543 | * fields. */ | |
544 | bool | |
545 | flow_wildcards_is_exact(const struct flow_wildcards *wc) | |
546 | { | |
d8ae4d67 | 547 | int i; |
00561f41 | 548 | |
d8ae4d67 | 549 | if (wc->wildcards |
8368c090 | 550 | || wc->tun_id_mask != htonll(UINT64_MAX) |
d8ae4d67 | 551 | || wc->nw_src_mask != htonl(UINT32_MAX) |
66642cb4 | 552 | || wc->nw_dst_mask != htonl(UINT32_MAX) |
d31f1109 JP |
553 | || wc->vlan_tci_mask != htons(UINT16_MAX) |
554 | || !ipv6_mask_is_exact(&wc->ipv6_src_mask) | |
555 | || !ipv6_mask_is_exact(&wc->ipv6_dst_mask)) { | |
d8ae4d67 BP |
556 | return false; |
557 | } | |
558 | ||
559 | for (i = 0; i < FLOW_N_REGS; i++) { | |
d84d4b88 | 560 | if (wc->reg_masks[i] != UINT32_MAX) { |
d8ae4d67 BP |
561 | return false; |
562 | } | |
563 | } | |
564 | ||
565 | return true; | |
b5d97350 BP |
566 | } |
567 | ||
568 | /* Initializes 'dst' as the combination of wildcards in 'src1' and 'src2'. | |
569 | * That is, a bit or a field is wildcarded in 'dst' if it is wildcarded in | |
570 | * 'src1' or 'src2' or both. */ | |
571 | void | |
572 | flow_wildcards_combine(struct flow_wildcards *dst, | |
573 | const struct flow_wildcards *src1, | |
574 | const struct flow_wildcards *src2) | |
575 | { | |
b6c9e612 | 576 | int i; |
b5d97350 | 577 | |
d8ae4d67 | 578 | dst->wildcards = src1->wildcards | src2->wildcards; |
8368c090 | 579 | dst->tun_id_mask = src1->tun_id_mask & src2->tun_id_mask; |
b5d97350 BP |
580 | dst->nw_src_mask = src1->nw_src_mask & src2->nw_src_mask; |
581 | dst->nw_dst_mask = src1->nw_dst_mask & src2->nw_dst_mask; | |
d31f1109 JP |
582 | dst->ipv6_src_mask = ipv6_addr_bitand(&src1->ipv6_src_mask, |
583 | &src2->ipv6_src_mask); | |
584 | dst->ipv6_dst_mask = ipv6_addr_bitand(&src1->ipv6_dst_mask, | |
585 | &src2->ipv6_dst_mask); | |
b6c9e612 BP |
586 | for (i = 0; i < FLOW_N_REGS; i++) { |
587 | dst->reg_masks[i] = src1->reg_masks[i] & src2->reg_masks[i]; | |
588 | } | |
66642cb4 | 589 | dst->vlan_tci_mask = src1->vlan_tci_mask & src2->vlan_tci_mask; |
b5d97350 BP |
590 | } |
591 | ||
592 | /* Returns a hash of the wildcards in 'wc'. */ | |
593 | uint32_t | |
1006cda6 | 594 | flow_wildcards_hash(const struct flow_wildcards *wc, uint32_t basis) |
b5d97350 | 595 | { |
d8ae4d67 BP |
596 | /* If you change struct flow_wildcards and thereby trigger this |
597 | * assertion, please check that the new struct flow_wildcards has no holes | |
598 | * in it before you update the assertion. */ | |
d31f1109 | 599 | BUILD_ASSERT_DECL(sizeof *wc == 56 + FLOW_N_REGS * 4); |
1006cda6 | 600 | return hash_bytes(wc, sizeof *wc, basis); |
b5d97350 BP |
601 | } |
602 | ||
603 | /* Returns true if 'a' and 'b' represent the same wildcards, false if they are | |
604 | * different. */ | |
605 | bool | |
606 | flow_wildcards_equal(const struct flow_wildcards *a, | |
607 | const struct flow_wildcards *b) | |
608 | { | |
b6c9e612 BP |
609 | int i; |
610 | ||
d8ae4d67 | 611 | if (a->wildcards != b->wildcards |
8368c090 | 612 | || a->tun_id_mask != b->tun_id_mask |
d8ae4d67 | 613 | || a->nw_src_mask != b->nw_src_mask |
66642cb4 | 614 | || a->nw_dst_mask != b->nw_dst_mask |
d31f1109 JP |
615 | || a->vlan_tci_mask != b->vlan_tci_mask |
616 | || !ipv6_addr_equals(&a->ipv6_src_mask, &b->ipv6_src_mask) | |
617 | || !ipv6_addr_equals(&a->ipv6_dst_mask, &b->ipv6_dst_mask)) { | |
b6c9e612 BP |
618 | return false; |
619 | } | |
620 | ||
621 | for (i = 0; i < FLOW_N_REGS; i++) { | |
622 | if (a->reg_masks[i] != b->reg_masks[i]) { | |
623 | return false; | |
624 | } | |
625 | } | |
626 | ||
627 | return true; | |
b5d97350 BP |
628 | } |
629 | ||
630 | /* Returns true if at least one bit or field is wildcarded in 'a' but not in | |
631 | * 'b', false otherwise. */ | |
632 | bool | |
633 | flow_wildcards_has_extra(const struct flow_wildcards *a, | |
634 | const struct flow_wildcards *b) | |
635 | { | |
b6c9e612 | 636 | int i; |
d31f1109 | 637 | struct in6_addr ipv6_masked; |
b6c9e612 BP |
638 | |
639 | for (i = 0; i < FLOW_N_REGS; i++) { | |
640 | if ((a->reg_masks[i] & b->reg_masks[i]) != b->reg_masks[i]) { | |
641 | return true; | |
642 | } | |
643 | } | |
644 | ||
d31f1109 JP |
645 | ipv6_masked = ipv6_addr_bitand(&a->ipv6_src_mask, &b->ipv6_src_mask); |
646 | if (!ipv6_addr_equals(&ipv6_masked, &b->ipv6_src_mask)) { | |
647 | return true; | |
648 | } | |
649 | ||
650 | ipv6_masked = ipv6_addr_bitand(&a->ipv6_dst_mask, &b->ipv6_dst_mask); | |
651 | if (!ipv6_addr_equals(&ipv6_masked, &b->ipv6_dst_mask)) { | |
652 | return true; | |
653 | } | |
654 | ||
d8ae4d67 | 655 | return (a->wildcards & ~b->wildcards |
8368c090 | 656 | || (a->tun_id_mask & b->tun_id_mask) != b->tun_id_mask |
b5d97350 | 657 | || (a->nw_src_mask & b->nw_src_mask) != b->nw_src_mask |
66642cb4 BP |
658 | || (a->nw_dst_mask & b->nw_dst_mask) != b->nw_dst_mask |
659 | || (a->vlan_tci_mask & b->vlan_tci_mask) != b->vlan_tci_mask); | |
b5d97350 BP |
660 | } |
661 | ||
494e43a5 | 662 | static bool |
d8ae4d67 | 663 | set_nw_mask(ovs_be32 *maskp, ovs_be32 mask) |
494e43a5 | 664 | { |
0596e897 | 665 | if (ip_is_cidr(mask)) { |
494e43a5 BP |
666 | *maskp = mask; |
667 | return true; | |
668 | } else { | |
669 | return false; | |
670 | } | |
671 | } | |
672 | ||
673 | /* Sets the IP (or ARP) source wildcard mask to CIDR 'mask' (consisting of N | |
674 | * high-order 1-bit and 32-N low-order 0-bits). Returns true if successful, | |
675 | * false if 'mask' is not a CIDR mask. */ | |
676 | bool | |
677 | flow_wildcards_set_nw_src_mask(struct flow_wildcards *wc, ovs_be32 mask) | |
678 | { | |
d8ae4d67 | 679 | return set_nw_mask(&wc->nw_src_mask, mask); |
494e43a5 BP |
680 | } |
681 | ||
682 | /* Sets the IP (or ARP) destination wildcard mask to CIDR 'mask' (consisting of | |
683 | * N high-order 1-bit and 32-N low-order 0-bits). Returns true if successful, | |
684 | * false if 'mask' is not a CIDR mask. */ | |
685 | bool | |
686 | flow_wildcards_set_nw_dst_mask(struct flow_wildcards *wc, ovs_be32 mask) | |
687 | { | |
d8ae4d67 | 688 | return set_nw_mask(&wc->nw_dst_mask, mask); |
494e43a5 | 689 | } |
b6c9e612 | 690 | |
d31f1109 JP |
691 | static bool |
692 | set_ipv6_mask(struct in6_addr *maskp, const struct in6_addr *mask) | |
693 | { | |
694 | if (ipv6_is_cidr(mask)) { | |
695 | *maskp = *mask; | |
696 | return true; | |
697 | } else { | |
698 | return false; | |
699 | } | |
700 | } | |
701 | ||
702 | /* Sets the IPv6 source wildcard mask to CIDR 'mask' (consisting of N | |
703 | * high-order 1-bit and 128-N low-order 0-bits). Returns true if successful, | |
704 | * false if 'mask' is not a CIDR mask. */ | |
705 | bool | |
706 | flow_wildcards_set_ipv6_src_mask(struct flow_wildcards *wc, | |
707 | const struct in6_addr *mask) | |
708 | { | |
709 | return set_ipv6_mask(&wc->ipv6_src_mask, mask); | |
710 | } | |
711 | ||
712 | /* Sets the IPv6 destination wildcard mask to CIDR 'mask' (consisting of | |
713 | * N high-order 1-bit and 128-N low-order 0-bits). Returns true if | |
714 | * successful, false if 'mask' is not a CIDR mask. */ | |
715 | bool | |
716 | flow_wildcards_set_ipv6_dst_mask(struct flow_wildcards *wc, | |
717 | const struct in6_addr *mask) | |
718 | { | |
719 | return set_ipv6_mask(&wc->ipv6_dst_mask, mask); | |
720 | } | |
721 | ||
b6c9e612 BP |
722 | /* Sets the wildcard mask for register 'idx' in 'wc' to 'mask'. |
723 | * (A 0-bit indicates a wildcard bit.) */ | |
724 | void | |
725 | flow_wildcards_set_reg_mask(struct flow_wildcards *wc, int idx, uint32_t mask) | |
726 | { | |
d8ae4d67 | 727 | wc->reg_masks[idx] = mask; |
b6c9e612 | 728 | } |
ff55ea1f | 729 | |
db7f8281 BP |
730 | /* Returns the wildcard bitmask for the Ethernet destination address |
731 | * that 'wc' specifies. The bitmask has a 0 in each bit that is wildcarded | |
732 | * and a 1 in each bit that must match. */ | |
733 | const uint8_t * | |
734 | flow_wildcards_to_dl_dst_mask(flow_wildcards_t wc) | |
735 | { | |
736 | static const uint8_t no_wild[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
737 | static const uint8_t addr_wild[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
738 | static const uint8_t mcast_wild[] = {0xfe, 0xff, 0xff, 0xff, 0xff, 0xff}; | |
739 | static const uint8_t all_wild[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | |
740 | ||
741 | switch (wc & (FWW_DL_DST | FWW_ETH_MCAST)) { | |
742 | case 0: return no_wild; | |
743 | case FWW_DL_DST: return addr_wild; | |
744 | case FWW_ETH_MCAST: return mcast_wild; | |
745 | case FWW_DL_DST | FWW_ETH_MCAST: return all_wild; | |
746 | } | |
747 | NOT_REACHED(); | |
748 | } | |
749 | ||
750 | /* Returns true if 'mask' is a valid wildcard bitmask for the Ethernet | |
751 | * destination address. Valid bitmasks are either all-bits-0 or all-bits-1, | |
752 | * except that the multicast bit may differ from the rest of the bits. So, | |
753 | * there are four possible valid bitmasks: | |
754 | * | |
755 | * - 00:00:00:00:00:00 | |
756 | * - 01:00:00:00:00:00 | |
757 | * - fe:ff:ff:ff:ff:ff | |
758 | * - ff:ff:ff:ff:ff:ff | |
759 | * | |
760 | * All other bitmasks are invalid. */ | |
761 | bool | |
762 | flow_wildcards_is_dl_dst_mask_valid(const uint8_t mask[ETH_ADDR_LEN]) | |
763 | { | |
764 | switch (mask[0]) { | |
765 | case 0x00: | |
766 | case 0x01: | |
767 | return (mask[1] | mask[2] | mask[3] | mask[4] | mask[5]) == 0x00; | |
768 | ||
769 | case 0xfe: | |
770 | case 0xff: | |
771 | return (mask[1] & mask[2] & mask[3] & mask[4] & mask[5]) == 0xff; | |
772 | ||
773 | default: | |
774 | return false; | |
775 | } | |
776 | } | |
777 | ||
778 | /* Returns 'wc' with the FWW_DL_DST and FWW_ETH_MCAST bits modified | |
779 | * appropriately to match 'mask'. | |
780 | * | |
781 | * This function will assert-fail if 'mask' is invalid. Only 'mask' values | |
782 | * accepted by flow_wildcards_is_dl_dst_mask_valid() are allowed. */ | |
783 | flow_wildcards_t | |
784 | flow_wildcards_set_dl_dst_mask(flow_wildcards_t wc, | |
785 | const uint8_t mask[ETH_ADDR_LEN]) | |
786 | { | |
787 | assert(flow_wildcards_is_dl_dst_mask_valid(mask)); | |
788 | ||
789 | switch (mask[0]) { | |
790 | case 0x00: | |
791 | return wc | FWW_DL_DST | FWW_ETH_MCAST; | |
792 | ||
793 | case 0x01: | |
794 | return (wc | FWW_DL_DST) & ~FWW_ETH_MCAST; | |
795 | ||
796 | case 0xfe: | |
797 | return (wc & ~FWW_DL_DST) | FWW_ETH_MCAST; | |
798 | ||
799 | case 0xff: | |
800 | return wc & ~(FWW_DL_DST | FWW_ETH_MCAST); | |
801 | ||
802 | default: | |
803 | NOT_REACHED(); | |
804 | } | |
805 | } | |
806 | ||
ff55ea1f EJ |
807 | /* Hashes 'flow' based on its L2 through L4 protocol information. */ |
808 | uint32_t | |
809 | flow_hash_symmetric_l4(const struct flow *flow, uint32_t basis) | |
810 | { | |
811 | struct { | |
d31f1109 JP |
812 | union { |
813 | ovs_be32 ipv4_addr; | |
814 | struct in6_addr ipv6_addr; | |
815 | }; | |
ff55ea1f EJ |
816 | ovs_be16 eth_type; |
817 | ovs_be16 vlan_tci; | |
818 | ovs_be16 tp_addr; | |
819 | uint8_t eth_addr[ETH_ADDR_LEN]; | |
820 | uint8_t ip_proto; | |
821 | } fields; | |
822 | ||
823 | int i; | |
824 | ||
825 | memset(&fields, 0, sizeof fields); | |
826 | for (i = 0; i < ETH_ADDR_LEN; i++) { | |
827 | fields.eth_addr[i] = flow->dl_src[i] ^ flow->dl_dst[i]; | |
828 | } | |
829 | fields.vlan_tci = flow->vlan_tci & htons(VLAN_VID_MASK); | |
830 | fields.eth_type = flow->dl_type; | |
3e3eda95 EJ |
831 | |
832 | /* UDP source and destination port are not taken into account because they | |
833 | * will not necessarily be symmetric in a bidirectional flow. */ | |
ff55ea1f | 834 | if (fields.eth_type == htons(ETH_TYPE_IP)) { |
d31f1109 JP |
835 | fields.ipv4_addr = flow->nw_src ^ flow->nw_dst; |
836 | fields.ip_proto = flow->nw_proto; | |
3e3eda95 | 837 | if (fields.ip_proto == IPPROTO_TCP) { |
d31f1109 JP |
838 | fields.tp_addr = flow->tp_src ^ flow->tp_dst; |
839 | } | |
840 | } else if (fields.eth_type == htons(ETH_TYPE_IPV6)) { | |
841 | const uint8_t *a = &flow->ipv6_src.s6_addr[0]; | |
842 | const uint8_t *b = &flow->ipv6_dst.s6_addr[0]; | |
843 | uint8_t *ipv6_addr = &fields.ipv6_addr.s6_addr[0]; | |
844 | ||
845 | for (i=0; i<16; i++) { | |
846 | ipv6_addr[i] = a[i] ^ b[i]; | |
847 | } | |
ff55ea1f | 848 | fields.ip_proto = flow->nw_proto; |
3e3eda95 | 849 | if (fields.ip_proto == IPPROTO_TCP) { |
ff55ea1f | 850 | fields.tp_addr = flow->tp_src ^ flow->tp_dst; |
ff55ea1f | 851 | } |
ff55ea1f EJ |
852 | } |
853 | return hash_bytes(&fields, sizeof fields, basis); | |
854 | } |