- struct parsed_flow pf;
- struct ofpbuf *buffer;
- struct ofp_flow_mod *ofm;
-
- /* parse_ofp_str() will expand and reallocate the data in 'buffer', so we
- * can't keep pointers to across the parse_ofp_str() call. */
- make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
- parse_ofp_str(&pf, buffer, string);
-
- ofm = buffer->data;
- ofputil_cls_rule_to_match(&pf.rule, NXFF_OPENFLOW10, &ofm->match);
- ofm->command = htons(command);
- ofm->cookie = htonll(pf.cookie);
- ofm->idle_timeout = htons(pf.idle_timeout);
- ofm->hard_timeout = htons(pf.hard_timeout);
- ofm->buffer_id = htonl(UINT32_MAX);
- ofm->out_port = htons(pf.out_port);
- ofm->priority = htons(pf.rule.priority);
- update_openflow_length(buffer);
-
- return buffer;
+ bool is_del = command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT;
+ enum nx_flow_format min_format, next_format;
+ struct ofpbuf actions;
+ struct ofpbuf *ofm;
+ struct flow_mod fm;
+
+ ofpbuf_init(&actions, 64);
+ parse_ofp_str(&fm, NULL, is_del ? NULL : &actions, string);
+ fm.command = command;
+
+ min_format = ofputil_min_flow_format(&fm.cr, true, fm.cookie);
+ next_format = MAX(*cur_format, min_format);
+ if (next_format != *cur_format) {
+ struct ofpbuf *sff = ofputil_make_set_flow_format(next_format);
+ list_push_back(packets, &sff->list_node);
+ *cur_format = next_format;
+ }
+
+ ofm = ofputil_encode_flow_mod(&fm, *cur_format);
+ list_push_back(packets, &ofm->list_node);
+
+ ofpbuf_uninit(&actions);