#include <string.h>
#include "byte-order.h"
#include "coverage.h"
-#include "dpif.h"
#include "dynamic-string.h"
#include "hash.h"
#include "ofpbuf.h"
#include "openflow/openflow.h"
-#include "openvswitch/datapath-protocol.h"
#include "packets.h"
#include "unaligned.h"
#include "vlog.h"
return retval;
}
-/* Extracts the flow stats for a packet. The 'flow' and 'packet'
- * arguments must have been initialized through a call to flow_extract().
- */
+/* For every bit of a field that is wildcarded in 'wildcards', sets the
+ * corresponding bit in 'flow' to zero. */
void
-flow_extract_stats(const struct flow *flow, struct ofpbuf *packet,
- struct dpif_flow_stats *stats)
+flow_zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards)
{
- memset(stats, 0, sizeof(*stats));
+ const flow_wildcards_t wc = wildcards->wildcards;
+ int i;
- if ((flow->dl_type == htons(ETH_TYPE_IP)) && packet->l4) {
- if ((flow->nw_proto == IPPROTO_TCP) && packet->l7) {
- struct tcp_header *tcp = packet->l4;
- stats->tcp_flags = TCP_FLAGS(tcp->tcp_ctl);
- }
- }
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 1);
- stats->n_bytes = packet->size;
- stats->n_packets = 1;
+ for (i = 0; i < FLOW_N_REGS; i++) {
+ flow->regs[i] &= wildcards->reg_masks[i];
+ }
+ flow->tun_id &= wildcards->tun_id_mask;
+ flow->nw_src &= wildcards->nw_src_mask;
+ flow->nw_dst &= wildcards->nw_dst_mask;
+ if (wc & FWW_IN_PORT) {
+ flow->in_port = 0;
+ }
+ flow->vlan_tci &= wildcards->vlan_tci_mask;
+ if (wc & FWW_DL_TYPE) {
+ flow->dl_type = 0;
+ }
+ if (wc & FWW_TP_SRC) {
+ flow->tp_src = 0;
+ }
+ if (wc & FWW_TP_DST) {
+ flow->tp_dst = 0;
+ }
+ if (wc & FWW_DL_SRC) {
+ memset(flow->dl_src, 0, sizeof flow->dl_src);
+ }
+ if (wc & FWW_DL_DST) {
+ flow->dl_dst[0] &= 0x01;
+ memset(&flow->dl_dst[1], 0, 5);
+ }
+ if (wc & FWW_ETH_MCAST) {
+ flow->dl_dst[0] &= 0xfe;
+ }
+ if (wc & FWW_NW_PROTO) {
+ flow->nw_proto = 0;
+ }
+ if (wc & FWW_NW_TOS) {
+ flow->nw_tos = 0;
+ }
+ if (wc & FWW_ARP_SHA) {
+ memset(flow->arp_sha, 0, sizeof flow->arp_sha);
+ }
+ if (wc & FWW_ARP_THA) {
+ memset(flow->arp_tha, 0, sizeof flow->arp_tha);
+ }
+ flow->ipv6_src = ipv6_addr_bitand(&flow->ipv6_src,
+ &wildcards->ipv6_src_mask);
+ flow->ipv6_dst = ipv6_addr_bitand(&flow->ipv6_dst,
+ &wildcards->ipv6_dst_mask);
+ if (wc & FWW_ND_TARGET) {
+ memset(&flow->nd_target, 0, sizeof flow->nd_target);
+ }
}
char *
{
int i;
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 1);
+
if (wc->wildcards
|| wc->tun_id_mask != htonll(UINT64_MAX)
|| wc->nw_src_mask != htonl(UINT32_MAX)
return true;
}
+/* Returns true if 'wc' matches every packet, false if 'wc' fixes any bits or
+ * fields. */
+bool
+flow_wildcards_is_catchall(const struct flow_wildcards *wc)
+{
+ int i;
+
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 1);
+
+ if (wc->wildcards != FWW_ALL
+ || wc->tun_id_mask != htonll(0)
+ || wc->nw_src_mask != htonl(0)
+ || wc->nw_dst_mask != htonl(0)
+ || wc->vlan_tci_mask != htons(0)
+ || !ipv6_mask_is_any(&wc->ipv6_src_mask)
+ || !ipv6_mask_is_any(&wc->ipv6_dst_mask)) {
+ return false;
+ }
+
+ for (i = 0; i < FLOW_N_REGS; i++) {
+ if (wc->reg_masks[i] != 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
/* Initializes 'dst' as the combination of wildcards in 'src1' and 'src2'.
* That is, a bit or a field is wildcarded in 'dst' if it is wildcarded in
* 'src1' or 'src2' or both. */