netflow: Move packet definitions to header file.
[openvswitch] / lib / flow.c
index ec233bc94d5a1438336e00832ac06d010e0f2ea2..922412fd8ce53cdb24e32c47ff69b447fc27ed25 100644 (file)
@@ -148,7 +148,7 @@ parse_ipv6(struct ofpbuf *packet, struct flow *flow)
     flow->ipv6_dst = nh->ip6_dst;
 
     tc_flow = get_unaligned_be32(&nh->ip6_flow);
-    flow->nw_tos = ntohl(tc_flow) >> 4;
+    flow->nw_tos = ntohl(tc_flow) >> 20;
     flow->ipv6_label = tc_flow & htonl(IPV6_LABEL_MASK);
     flow->nw_ttl = nh->ip6_hlim;
     flow->nw_proto = IPPROTO_NONE;
@@ -203,11 +203,14 @@ parse_ipv6(struct ofpbuf *packet, struct flow *flow)
             }
 
             /* We only process the first fragment. */
-            flow->nw_frag = FLOW_NW_FRAG_ANY;
-            if ((frag_hdr->ip6f_offlg & IP6F_OFF_MASK) != htons(0)) {
-                flow->nw_frag |= FLOW_NW_FRAG_LATER;
-                nexthdr = IPPROTO_FRAGMENT;
-                break;
+            if (frag_hdr->ip6f_offlg != htons(0)) {
+                if ((frag_hdr->ip6f_offlg & IP6F_OFF_MASK) == htons(0)) {
+                    flow->nw_frag = FLOW_NW_FRAG_ANY;
+                } else {
+                    flow->nw_frag |= FLOW_NW_FRAG_LATER;
+                    nexthdr = IPPROTO_FRAGMENT;
+                    break;
+                }
             }
         }
     }
@@ -452,13 +455,13 @@ flow_zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards)
     }
     flow->vlan_tci &= wildcards->vlan_tci_mask;
     if (wc & FWW_DL_TYPE) {
-        flow->dl_type = 0;
+        flow->dl_type = htons(0);
     }
     if (wc & FWW_TP_SRC) {
-        flow->tp_src = 0;
+        flow->tp_src = htons(0);
     }
     if (wc & FWW_TP_DST) {
-        flow->tp_dst = 0;
+        flow->tp_dst = htons(0);
     }
     if (wc & FWW_DL_SRC) {
         memset(flow->dl_src, 0, sizeof flow->dl_src);
@@ -935,6 +938,44 @@ flow_hash_fields_valid(enum nx_hash_fields fields)
         || fields == NX_HASH_FIELDS_SYMMETRIC_L4;
 }
 
+/* Sets the VLAN VID that 'flow' matches to 'vid', which is interpreted as an
+ * OpenFlow 1.0 "dl_vlan" value:
+ *
+ *      - If it is in the range 0...4095, 'flow->vlan_tci' is set to match
+ *        that VLAN.  Any existing PCP match is unchanged (it becomes 0 if
+ *        'flow' previously matched packets without a VLAN header).
+ *
+ *      - If it is OFP_VLAN_NONE, 'flow->vlan_tci' is set to match a packet
+ *        without a VLAN tag.
+ *
+ *      - Other values of 'vid' should not be used. */
+void
+flow_set_vlan_vid(struct flow *flow, ovs_be16 vid)
+{
+    if (vid == htons(OFP_VLAN_NONE)) {
+        flow->vlan_tci = htons(0);
+    } else {
+        vid &= htons(VLAN_VID_MASK);
+        flow->vlan_tci &= ~htons(VLAN_VID_MASK);
+        flow->vlan_tci |= htons(VLAN_CFI) | vid;
+    }
+}
+
+/* Sets the VLAN PCP that 'flow' matches to 'pcp', which should be in the
+ * range 0...7.
+ *
+ * This function has no effect on the VLAN ID that 'flow' matches.
+ *
+ * After calling this function, 'flow' will not match packets without a VLAN
+ * header. */
+void
+flow_set_vlan_pcp(struct flow *flow, uint8_t pcp)
+{
+    pcp &= 0x07;
+    flow->vlan_tci &= ~htons(VLAN_PCP_MASK);
+    flow->vlan_tci |= htons((pcp << VLAN_PCP_SHIFT) | VLAN_CFI);
+}
+
 /* Puts into 'b' a packet that flow_extract() would parse as having the given
  * 'flow'.
  *
@@ -979,6 +1020,7 @@ flow_compose(struct ofpbuf *b, const struct flow *flow)
                 b->l4 = tcp = ofpbuf_put_zeros(b, sizeof *tcp);
                 tcp->tcp_src = flow->tp_src;
                 tcp->tcp_dst = flow->tp_dst;
+                tcp->tcp_ctl = TCP_CTL(0, 5);
             } else if (flow->nw_proto == IPPROTO_UDP) {
                 struct udp_header *udp;
 
@@ -993,6 +1035,9 @@ flow_compose(struct ofpbuf *b, const struct flow *flow)
                 icmp->icmp_code = ntohs(flow->tp_dst);
             }
         }
+
+        ip->ip_tot_len = htons((uint8_t *) b->data + b->size
+                               - (uint8_t *) b->l3);
     } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
         /* XXX */
     } else if (flow->dl_type == htons(ETH_TYPE_ARP)) {