]>
git.proxmox.com Git - ovs.git/blob - lib/flow.c
2 * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <sys/types.h>
20 #include <netinet/in.h>
23 #include "byte-order.h"
26 #include "dynamic-string.h"
29 #include "openflow/openflow.h"
30 #include "openvswitch/datapath-protocol.h"
32 #include "unaligned.h"
35 VLOG_DEFINE_THIS_MODULE(flow
);
37 COVERAGE_DEFINE(flow_extract
);
39 static struct arp_eth_header
*
40 pull_arp(struct ofpbuf
*packet
)
42 return ofpbuf_try_pull(packet
, ARP_ETH_HEADER_LEN
);
45 static struct ip_header
*
46 pull_ip(struct ofpbuf
*packet
)
48 if (packet
->size
>= IP_HEADER_LEN
) {
49 struct ip_header
*ip
= packet
->data
;
50 int ip_len
= IP_IHL(ip
->ip_ihl_ver
) * 4;
51 if (ip_len
>= IP_HEADER_LEN
&& packet
->size
>= ip_len
) {
52 return ofpbuf_pull(packet
, ip_len
);
58 static struct tcp_header
*
59 pull_tcp(struct ofpbuf
*packet
)
61 if (packet
->size
>= TCP_HEADER_LEN
) {
62 struct tcp_header
*tcp
= packet
->data
;
63 int tcp_len
= TCP_OFFSET(tcp
->tcp_ctl
) * 4;
64 if (tcp_len
>= TCP_HEADER_LEN
&& packet
->size
>= tcp_len
) {
65 return ofpbuf_pull(packet
, tcp_len
);
71 static struct udp_header
*
72 pull_udp(struct ofpbuf
*packet
)
74 return ofpbuf_try_pull(packet
, UDP_HEADER_LEN
);
77 static struct icmp_header
*
78 pull_icmp(struct ofpbuf
*packet
)
80 return ofpbuf_try_pull(packet
, ICMP_HEADER_LEN
);
84 parse_vlan(struct ofpbuf
*b
, struct flow
*flow
)
87 ovs_be16 eth_type
; /* ETH_TYPE_VLAN */
91 if (b
->size
>= sizeof(struct qtag_prefix
) + sizeof(ovs_be16
)) {
92 struct qtag_prefix
*qp
= ofpbuf_pull(b
, sizeof *qp
);
93 flow
->vlan_tci
= qp
->tci
| htons(VLAN_CFI
);
98 parse_ethertype(struct ofpbuf
*b
)
100 struct llc_snap_header
*llc
;
103 proto
= *(ovs_be16
*) ofpbuf_pull(b
, sizeof proto
);
104 if (ntohs(proto
) >= ETH_TYPE_MIN
) {
108 if (b
->size
< sizeof *llc
) {
109 return htons(FLOW_DL_TYPE_NONE
);
113 if (llc
->llc
.llc_dsap
!= LLC_DSAP_SNAP
114 || llc
->llc
.llc_ssap
!= LLC_SSAP_SNAP
115 || llc
->llc
.llc_cntl
!= LLC_CNTL_SNAP
116 || memcmp(llc
->snap
.snap_org
, SNAP_ORG_ETHERNET
,
117 sizeof llc
->snap
.snap_org
)) {
118 return htons(FLOW_DL_TYPE_NONE
);
121 ofpbuf_pull(b
, sizeof *llc
);
122 return llc
->snap
.snap_type
;
125 /* Initializes 'flow' members from 'packet', 'tun_id', and 'in_port.
126 * Initializes 'packet' header pointers as follows:
128 * - packet->l2 to the start of the Ethernet header.
130 * - packet->l3 to just past the Ethernet header, or just past the
131 * vlan_header if one is present, to the first byte of the payload of the
134 * - packet->l4 to just past the IPv4 header, if one is present and has a
135 * correct length, and otherwise NULL.
137 * - packet->l7 to just past the TCP or UDP or ICMP header, if one is
138 * present and has a correct length, and otherwise NULL.
141 flow_extract(struct ofpbuf
*packet
, ovs_be64 tun_id
, uint16_t in_port
,
144 struct ofpbuf b
= *packet
;
145 struct eth_header
*eth
;
148 COVERAGE_INC(flow_extract
);
150 memset(flow
, 0, sizeof *flow
);
151 flow
->tun_id
= tun_id
;
152 flow
->in_port
= in_port
;
159 if (b
.size
< sizeof *eth
) {
165 memcpy(flow
->dl_src
, eth
->eth_src
, ETH_ADDR_LEN
);
166 memcpy(flow
->dl_dst
, eth
->eth_dst
, ETH_ADDR_LEN
);
168 /* dl_type, vlan_tci. */
169 ofpbuf_pull(&b
, ETH_ADDR_LEN
* 2);
170 if (eth
->eth_type
== htons(ETH_TYPE_VLAN
)) {
171 parse_vlan(&b
, flow
);
173 flow
->dl_type
= parse_ethertype(&b
);
177 if (flow
->dl_type
== htons(ETH_TYPE_IP
)) {
178 const struct ip_header
*nh
= pull_ip(&b
);
180 flow
->nw_src
= get_unaligned_be32(&nh
->ip_src
);
181 flow
->nw_dst
= get_unaligned_be32(&nh
->ip_dst
);
182 flow
->nw_tos
= nh
->ip_tos
& IP_DSCP_MASK
;
183 flow
->nw_proto
= nh
->ip_proto
;
185 if (!IP_IS_FRAGMENT(nh
->ip_frag_off
)) {
186 if (flow
->nw_proto
== IPPROTO_TCP
) {
187 const struct tcp_header
*tcp
= pull_tcp(&b
);
189 flow
->tp_src
= tcp
->tcp_src
;
190 flow
->tp_dst
= tcp
->tcp_dst
;
193 } else if (flow
->nw_proto
== IPPROTO_UDP
) {
194 const struct udp_header
*udp
= pull_udp(&b
);
196 flow
->tp_src
= udp
->udp_src
;
197 flow
->tp_dst
= udp
->udp_dst
;
200 } else if (flow
->nw_proto
== IPPROTO_ICMP
) {
201 const struct icmp_header
*icmp
= pull_icmp(&b
);
203 flow
->icmp_type
= htons(icmp
->icmp_type
);
204 flow
->icmp_code
= htons(icmp
->icmp_code
);
212 } else if (flow
->dl_type
== htons(ETH_TYPE_ARP
)) {
213 const struct arp_eth_header
*arp
= pull_arp(&b
);
214 if (arp
&& arp
->ar_hrd
== htons(1)
215 && arp
->ar_pro
== htons(ETH_TYPE_IP
)
216 && arp
->ar_hln
== ETH_ADDR_LEN
217 && arp
->ar_pln
== 4) {
218 /* We only match on the lower 8 bits of the opcode. */
219 if (ntohs(arp
->ar_op
) <= 0xff) {
220 flow
->nw_proto
= ntohs(arp
->ar_op
);
223 if ((flow
->nw_proto
== ARP_OP_REQUEST
)
224 || (flow
->nw_proto
== ARP_OP_REPLY
)) {
225 flow
->nw_src
= arp
->ar_spa
;
226 flow
->nw_dst
= arp
->ar_tpa
;
233 /* Extracts the flow stats for a packet. The 'flow' and 'packet'
234 * arguments must have been initialized through a call to flow_extract().
237 flow_extract_stats(const struct flow
*flow
, struct ofpbuf
*packet
,
238 struct dpif_flow_stats
*stats
)
240 memset(stats
, 0, sizeof(*stats
));
242 if ((flow
->dl_type
== htons(ETH_TYPE_IP
)) && packet
->l4
) {
243 if ((flow
->nw_proto
== IPPROTO_TCP
) && packet
->l7
) {
244 struct tcp_header
*tcp
= packet
->l4
;
245 stats
->tcp_flags
= TCP_FLAGS(tcp
->tcp_ctl
);
249 stats
->n_bytes
= packet
->size
;
250 stats
->n_packets
= 1;
254 flow_to_string(const struct flow
*flow
)
256 struct ds ds
= DS_EMPTY_INITIALIZER
;
257 flow_format(&ds
, flow
);
262 flow_format(struct ds
*ds
, const struct flow
*flow
)
264 ds_put_format(ds
, "tunnel%#"PRIx64
":in_port%04"PRIx16
":tci(",
265 flow
->tun_id
, flow
->in_port
);
266 if (flow
->vlan_tci
) {
267 ds_put_format(ds
, "vlan%"PRIu16
",pcp%d",
268 vlan_tci_to_vid(flow
->vlan_tci
),
269 vlan_tci_to_pcp(flow
->vlan_tci
));
271 ds_put_char(ds
, '0');
273 ds_put_format(ds
, ") mac"ETH_ADDR_FMT
"->"ETH_ADDR_FMT
277 " ip"IP_FMT
"->"IP_FMT
278 " port%"PRIu16
"->%"PRIu16
,
279 ETH_ADDR_ARGS(flow
->dl_src
),
280 ETH_ADDR_ARGS(flow
->dl_dst
),
281 ntohs(flow
->dl_type
),
284 IP_ARGS(&flow
->nw_src
),
285 IP_ARGS(&flow
->nw_dst
),
287 ntohs(flow
->tp_dst
));
291 flow_print(FILE *stream
, const struct flow
*flow
)
293 char *s
= flow_to_string(flow
);
298 /* flow_wildcards functions. */
300 /* Initializes 'wc' as a set of wildcards that matches every packet. */
302 flow_wildcards_init_catchall(struct flow_wildcards
*wc
)
304 wc
->wildcards
= FWW_ALL
;
305 wc
->tun_id_mask
= htonll(0);
306 wc
->nw_src_mask
= htonl(0);
307 wc
->nw_dst_mask
= htonl(0);
308 memset(wc
->reg_masks
, 0, sizeof wc
->reg_masks
);
309 wc
->vlan_tci_mask
= htons(0);
313 /* Initializes 'wc' as an exact-match set of wildcards; that is, 'wc' does not
314 * wildcard any bits or fields. */
316 flow_wildcards_init_exact(struct flow_wildcards
*wc
)
319 wc
->tun_id_mask
= htonll(UINT64_MAX
);
320 wc
->nw_src_mask
= htonl(UINT32_MAX
);
321 wc
->nw_dst_mask
= htonl(UINT32_MAX
);
322 memset(wc
->reg_masks
, 0xff, sizeof wc
->reg_masks
);
323 wc
->vlan_tci_mask
= htons(UINT16_MAX
);
327 /* Returns true if 'wc' is exact-match, false if 'wc' wildcards any bits or
330 flow_wildcards_is_exact(const struct flow_wildcards
*wc
)
335 || wc
->tun_id_mask
!= htonll(UINT64_MAX
)
336 || wc
->nw_src_mask
!= htonl(UINT32_MAX
)
337 || wc
->nw_dst_mask
!= htonl(UINT32_MAX
)
338 || wc
->vlan_tci_mask
!= htons(UINT16_MAX
)) {
342 for (i
= 0; i
< FLOW_N_REGS
; i
++) {
343 if (wc
->reg_masks
[i
] != htonl(UINT32_MAX
)) {
351 /* Initializes 'dst' as the combination of wildcards in 'src1' and 'src2'.
352 * That is, a bit or a field is wildcarded in 'dst' if it is wildcarded in
353 * 'src1' or 'src2' or both. */
355 flow_wildcards_combine(struct flow_wildcards
*dst
,
356 const struct flow_wildcards
*src1
,
357 const struct flow_wildcards
*src2
)
361 dst
->wildcards
= src1
->wildcards
| src2
->wildcards
;
362 dst
->tun_id_mask
= src1
->tun_id_mask
& src2
->tun_id_mask
;
363 dst
->nw_src_mask
= src1
->nw_src_mask
& src2
->nw_src_mask
;
364 dst
->nw_dst_mask
= src1
->nw_dst_mask
& src2
->nw_dst_mask
;
365 for (i
= 0; i
< FLOW_N_REGS
; i
++) {
366 dst
->reg_masks
[i
] = src1
->reg_masks
[i
] & src2
->reg_masks
[i
];
368 dst
->vlan_tci_mask
= src1
->vlan_tci_mask
& src2
->vlan_tci_mask
;
371 /* Returns a hash of the wildcards in 'wc'. */
373 flow_wildcards_hash(const struct flow_wildcards
*wc
)
375 /* If you change struct flow_wildcards and thereby trigger this
376 * assertion, please check that the new struct flow_wildcards has no holes
377 * in it before you update the assertion. */
378 BUILD_ASSERT_DECL(sizeof *wc
== 24 + FLOW_N_REGS
* 4);
379 return hash_bytes(wc
, sizeof *wc
, 0);
382 /* Returns true if 'a' and 'b' represent the same wildcards, false if they are
385 flow_wildcards_equal(const struct flow_wildcards
*a
,
386 const struct flow_wildcards
*b
)
390 if (a
->wildcards
!= b
->wildcards
391 || a
->tun_id_mask
!= b
->tun_id_mask
392 || a
->nw_src_mask
!= b
->nw_src_mask
393 || a
->nw_dst_mask
!= b
->nw_dst_mask
394 || a
->vlan_tci_mask
!= b
->vlan_tci_mask
) {
398 for (i
= 0; i
< FLOW_N_REGS
; i
++) {
399 if (a
->reg_masks
[i
] != b
->reg_masks
[i
]) {
407 /* Returns true if at least one bit or field is wildcarded in 'a' but not in
408 * 'b', false otherwise. */
410 flow_wildcards_has_extra(const struct flow_wildcards
*a
,
411 const struct flow_wildcards
*b
)
415 for (i
= 0; i
< FLOW_N_REGS
; i
++) {
416 if ((a
->reg_masks
[i
] & b
->reg_masks
[i
]) != b
->reg_masks
[i
]) {
421 return (a
->wildcards
& ~b
->wildcards
422 || (a
->tun_id_mask
& b
->tun_id_mask
) != b
->tun_id_mask
423 || (a
->nw_src_mask
& b
->nw_src_mask
) != b
->nw_src_mask
424 || (a
->nw_dst_mask
& b
->nw_dst_mask
) != b
->nw_dst_mask
425 || (a
->vlan_tci_mask
& b
->vlan_tci_mask
) != b
->vlan_tci_mask
);
429 set_nw_mask(ovs_be32
*maskp
, ovs_be32 mask
)
431 if (ip_is_cidr(mask
)) {
439 /* Sets the IP (or ARP) source wildcard mask to CIDR 'mask' (consisting of N
440 * high-order 1-bit and 32-N low-order 0-bits). Returns true if successful,
441 * false if 'mask' is not a CIDR mask. */
443 flow_wildcards_set_nw_src_mask(struct flow_wildcards
*wc
, ovs_be32 mask
)
445 return set_nw_mask(&wc
->nw_src_mask
, mask
);
448 /* Sets the IP (or ARP) destination wildcard mask to CIDR 'mask' (consisting of
449 * N high-order 1-bit and 32-N low-order 0-bits). Returns true if successful,
450 * false if 'mask' is not a CIDR mask. */
452 flow_wildcards_set_nw_dst_mask(struct flow_wildcards
*wc
, ovs_be32 mask
)
454 return set_nw_mask(&wc
->nw_dst_mask
, mask
);
457 /* Sets the wildcard mask for register 'idx' in 'wc' to 'mask'.
458 * (A 0-bit indicates a wildcard bit.) */
460 flow_wildcards_set_reg_mask(struct flow_wildcards
*wc
, int idx
, uint32_t mask
)
462 wc
->reg_masks
[idx
] = mask
;
465 /* Hashes 'flow' based on its L2 through L4 protocol information. */
467 flow_hash_symmetric_l4(const struct flow
*flow
, uint32_t basis
)
474 uint8_t eth_addr
[ETH_ADDR_LEN
];
480 memset(&fields
, 0, sizeof fields
);
481 for (i
= 0; i
< ETH_ADDR_LEN
; i
++) {
482 fields
.eth_addr
[i
] = flow
->dl_src
[i
] ^ flow
->dl_dst
[i
];
484 fields
.vlan_tci
= flow
->vlan_tci
& htons(VLAN_VID_MASK
);
485 fields
.eth_type
= flow
->dl_type
;
486 if (fields
.eth_type
== htons(ETH_TYPE_IP
)) {
487 fields
.ip_addr
= flow
->nw_src
^ flow
->nw_dst
;
488 fields
.ip_proto
= flow
->nw_proto
;
489 if (fields
.ip_proto
== IPPROTO_TCP
|| fields
.ip_proto
== IPPROTO_UDP
) {
490 fields
.tp_addr
= flow
->tp_src
^ flow
->tp_dst
;
492 fields
.tp_addr
= htons(0);
495 fields
.ip_addr
= htonl(0);
497 fields
.tp_addr
= htons(0);
499 return hash_bytes(&fields
, sizeof fields
, basis
);