- len = b->size - start_ofs;
- remainder = len % OFP_ACTION_ALIGN;
- if (remainder) {
- ofpbuf_put_zeros(b, OFP_ACTION_ALIGN - remainder);
- }
- nan->len = htons(b->size - start_ofs);
- } else if (!strcasecmp(act, "move")) {
- struct nx_action_reg_move *move;
- move = ofpbuf_put_uninit(b, sizeof *move);
- nxm_parse_reg_move(move, arg);
- } else if (!strcasecmp(act, "load")) {
- struct nx_action_reg_load *load;
- load = ofpbuf_put_uninit(b, sizeof *load);
- nxm_parse_reg_load(load, arg);
- } else if (!strcasecmp(act, "multipath")) {
- struct nx_action_multipath *nam;
- nam = ofpbuf_put_uninit(b, sizeof *nam);
- multipath_parse(nam, arg);
- } else if (!strcasecmp(act, "output")) {
- put_output_action(b, str_to_u32(arg));
- } else if (!strcasecmp(act, "enqueue")) {
- char *sp = NULL;
- char *port_s = strtok_r(arg, ":q", &sp);
- char *queue = strtok_r(NULL, "", &sp);
- if (port_s == NULL || queue == NULL) {
- ovs_fatal(0, "\"enqueue\" syntax is \"enqueue:PORT:QUEUE\"");
- }
- put_enqueue_action(b, str_to_u32(port_s), str_to_u32(queue));
+static void
+parse_named_action(enum ofputil_action_code code, const struct flow *flow,
+ struct ofpbuf *b, char *arg)
+{
+ struct ofp_action_dl_addr *oada;
+ struct ofp_action_vlan_pcp *oavp;
+ struct ofp_action_vlan_vid *oavv;
+ struct ofp_action_nw_addr *oana;
+ struct ofp_action_tp_port *oata;
+
+ switch (code) {
+ case OFPUTIL_OFPAT10_OUTPUT:
+ parse_output(b, arg);
+ break;
+
+ case OFPUTIL_OFPAT10_SET_VLAN_VID:
+ oavv = ofputil_put_OFPAT10_SET_VLAN_VID(b);
+ oavv->vlan_vid = htons(str_to_u32(arg));
+ break;
+
+ case OFPUTIL_OFPAT10_SET_VLAN_PCP:
+ oavp = ofputil_put_OFPAT10_SET_VLAN_PCP(b);
+ oavp->vlan_pcp = str_to_u32(arg);
+ break;
+
+ case OFPUTIL_OFPAT10_STRIP_VLAN:
+ ofputil_put_OFPAT10_STRIP_VLAN(b);
+ break;
+
+ case OFPUTIL_OFPAT10_SET_DL_SRC:
+ case OFPUTIL_OFPAT10_SET_DL_DST:
+ oada = ofputil_put_action(code, b);
+ str_to_mac(arg, oada->dl_addr);
+ break;
+
+ case OFPUTIL_OFPAT10_SET_NW_SRC:
+ case OFPUTIL_OFPAT10_SET_NW_DST:
+ oana = ofputil_put_action(code, b);
+ str_to_ip(arg, &oana->nw_addr);
+ break;
+
+ case OFPUTIL_OFPAT10_SET_NW_TOS:
+ ofputil_put_OFPAT10_SET_NW_TOS(b)->nw_tos = str_to_u32(arg);
+ break;
+
+ case OFPUTIL_OFPAT10_SET_TP_SRC:
+ case OFPUTIL_OFPAT10_SET_TP_DST:
+ oata = ofputil_put_action(code, b);
+ oata->tp_port = htons(str_to_u32(arg));
+ break;
+
+ case OFPUTIL_OFPAT10_ENQUEUE:
+ parse_enqueue(b, arg);
+ break;
+
+ case OFPUTIL_NXAST_RESUBMIT:
+ parse_resubmit(b, arg);
+ break;
+
+ case OFPUTIL_NXAST_SET_TUNNEL:
+ parse_set_tunnel(b, arg);
+ break;
+
+ case OFPUTIL_NXAST_SET_QUEUE:
+ ofputil_put_NXAST_SET_QUEUE(b)->queue_id = htonl(str_to_u32(arg));
+ break;
+
+ case OFPUTIL_NXAST_POP_QUEUE:
+ ofputil_put_NXAST_POP_QUEUE(b);
+ break;
+
+ case OFPUTIL_NXAST_REG_MOVE:
+ nxm_parse_reg_move(ofputil_put_NXAST_REG_MOVE(b), arg);
+ break;
+
+ case OFPUTIL_NXAST_REG_LOAD:
+ nxm_parse_reg_load(ofputil_put_NXAST_REG_LOAD(b), arg);
+ break;
+
+ case OFPUTIL_NXAST_NOTE:
+ parse_note(b, arg);
+ break;
+
+ case OFPUTIL_NXAST_SET_TUNNEL64:
+ ofputil_put_NXAST_SET_TUNNEL64(b)->tun_id = htonll(str_to_u64(arg));
+ break;
+
+ case OFPUTIL_NXAST_MULTIPATH:
+ multipath_parse(ofputil_put_NXAST_MULTIPATH(b), arg);
+ break;
+
+ case OFPUTIL_NXAST_AUTOPATH:
+ autopath_parse(ofputil_put_NXAST_AUTOPATH(b), arg);
+ break;
+
+ case OFPUTIL_NXAST_BUNDLE:
+ bundle_parse(b, arg);
+ break;
+
+ case OFPUTIL_NXAST_BUNDLE_LOAD:
+ bundle_parse_load(b, arg);
+ break;
+
+ case OFPUTIL_NXAST_RESUBMIT_TABLE:
+ case OFPUTIL_NXAST_OUTPUT_REG:
+ NOT_REACHED();
+
+ case OFPUTIL_NXAST_LEARN:
+ learn_parse(b, arg, flow);
+ break;
+
+ case OFPUTIL_NXAST_EXIT:
+ ofputil_put_NXAST_EXIT(b);
+ break;
+
+ case OFPUTIL_NXAST_DEC_TTL:
+ ofputil_put_NXAST_DEC_TTL(b);
+ break;
+
+ case OFPUTIL_NXAST_FIN_TIMEOUT:
+ parse_fin_timeout(b, arg);
+ break;
+
+ case OFPUTIL_NXAST_CONTROLLER:
+ parse_controller(b, arg);
+ break;
+ }
+}
+
+static void
+str_to_action(const struct flow *flow, char *str, struct ofpbuf *b)
+{
+ char *pos, *act, *arg;
+ int n_actions;
+
+ pos = str;
+ n_actions = 0;
+ while (ofputil_parse_key_value(&pos, &act, &arg)) {
+ uint16_t port;
+ int code;
+
+ code = ofputil_action_code_from_name(act);
+ if (code >= 0) {
+ parse_named_action(code, flow, b, arg);