cls_rule_zero_wildcarded_fields(rule);
}
-/* Extract 'flow' with 'wildcards' into the OpenFlow match structure
- * 'match'.
+/* Convert 'rule' into the OpenFlow match structure 'match'. 'flow_format'
+ * must either NXFF_OPENFLOW10 or NXFF_TUN_ID_FROM_COOKIE.
*
- * 'flow_format' must either NXFF_OPENFLOW10 or NXFF_TUN_ID_FROM_COOKIE. In
- * the latter case only, 'match''s NXFW_TUN_ID bit will be filled in; otherwise
- * it is always set to 0. */
+ * The NXFF_TUN_ID_FROM_COOKIE flow format requires modifying the flow cookie.
+ * This function can help with that, if 'cookie_out' is nonnull. For
+ * NXFF_OPENFLOW10, or if the tunnel ID is wildcarded, 'cookie_in' will be
+ * copied directly to '*cookie_out'. For NXFF_TUN_ID_FROM_COOKIE when tunnel
+ * ID is matched, 'cookie_in' will be modified appropriately before setting
+ * '*cookie_out'.
+ */
void
ofputil_cls_rule_to_match(const struct cls_rule *rule,
enum nx_flow_format flow_format,
- struct ofp_match *match)
+ struct ofp_match *match,
+ ovs_be64 cookie_in, ovs_be64 *cookie_out)
{
const struct flow_wildcards *wc = &rule->wc;
unsigned int ofpfw;
if (wc->wildcards & FWW_NW_TOS) {
ofpfw |= OFPFW_NW_TOS;
}
- if (flow_format == NXFF_TUN_ID_FROM_COOKIE && wc->wildcards & FWW_TUN_ID) {
- ofpfw |= NXFW_TUN_ID;
+
+ /* Tunnel ID. */
+ if (flow_format == NXFF_TUN_ID_FROM_COOKIE) {
+ if (wc->wildcards & FWW_TUN_ID) {
+ ofpfw |= NXFW_TUN_ID;
+ } else {
+ uint32_t cookie_lo = ntohll(cookie_in);
+ uint32_t cookie_hi = ntohl(rule->flow.tun_id);
+ cookie_in = htonll(cookie_lo | ((uint64_t) cookie_hi << 32));
+ }
+ }
+ if (cookie_out) {
+ *cookie_out = cookie_in;
}
/* Translate VLANs. */
msg = ofpbuf_new(sizeof *ofm + actions_len);
ofm = put_openflow(sizeof *ofm, OFPT_FLOW_MOD, msg);
- ofputil_cls_rule_to_match(&fm->cr, flow_format, &ofm->match);
- if (flow_format != NXFF_TUN_ID_FROM_COOKIE
- || fm->cr.wc.wildcards & FWW_TUN_ID) {
- ofm->cookie = fm->cookie;
- } else {
- uint32_t cookie_lo = ntohll(fm->cookie);
- uint32_t cookie_hi = ntohl(fm->cr.flow.tun_id);
- ofm->cookie = htonll(cookie_lo | ((uint64_t) cookie_hi << 32));
- }
+ ofputil_cls_rule_to_match(&fm->cr, flow_format, &ofm->match,
+ fm->cookie, &ofm->cookie);
ofm->command = htons(fm->command);
ofm->idle_timeout = htons(fm->idle_timeout);
ofm->hard_timeout = htons(fm->hard_timeout);
type = fsr->aggregate ? OFPST_AGGREGATE : OFPST_FLOW;
ofsr = ofputil_make_stats_request(sizeof *ofsr, type, &msg);
- ofputil_cls_rule_to_match(&fsr->match, flow_format, &ofsr->match);
+ ofputil_cls_rule_to_match(&fsr->match, flow_format, &ofsr->match,
+ 0, NULL);
ofsr->table_id = fsr->table_id;
ofsr->out_port = htons(fsr->out_port);
} else if (flow_format == NXFF_NXM) {
ofm->header.length = htons(size);
ofm->cookie = 0;
ofm->priority = htons(MIN(rule->priority, UINT16_MAX));
- ofputil_cls_rule_to_match(rule, NXFF_OPENFLOW10, &ofm->match);
+ ofputil_cls_rule_to_match(rule, NXFF_OPENFLOW10, &ofm->match, 0, NULL);
ofm->command = htons(command);
return out;
}
ofs->length = htons(len);
ofs->table_id = 0;
ofs->pad = 0;
- ofputil_cls_rule_to_match(&rule->cr, ofconn->flow_format, &ofs->match);
+ ofputil_cls_rule_to_match(&rule->cr, ofconn->flow_format, &ofs->match,
+ rule->flow_cookie, &ofs->cookie);
calc_flow_duration(rule->created, &ofs->duration_sec, &ofs->duration_nsec);
- ofs->cookie = rule->flow_cookie;
ofs->priority = htons(rule->cr.priority);
ofs->idle_timeout = htons(rule->idle_timeout);
ofs->hard_timeout = htons(rule->hard_timeout);
struct ofpbuf *buf;
ofr = make_openflow(sizeof *ofr, OFPT_FLOW_REMOVED, &buf);
- ofputil_cls_rule_to_match(&rule->cr, ofconn->flow_format, &ofr->match);
- ofr->cookie = rule->flow_cookie;
+ ofputil_cls_rule_to_match(&rule->cr, ofconn->flow_format, &ofr->match,
+ rule->flow_cookie, &ofr->cookie);
ofr->priority = htons(rule->cr.priority);
ofr->reason = reason;
calc_flow_duration(rule->created, &ofr->duration_sec, &ofr->duration_nsec);