+void
+format_odp_flow_key(struct ds *ds, const struct odp_flow_key *key)
+{
+ ds_put_format(ds, "tun_id%#"PRIx64" in_port%d tci(",
+ ntohll(key->tun_id), key->in_port);
+ if (key->dl_tci) {
+ ds_put_format(ds, "vlan%"PRIu16",pcp%d",
+ vlan_tci_to_vid(key->dl_tci),
+ vlan_tci_to_pcp(key->dl_tci));
+ } else {
+ ds_put_char(ds, '0');
+ }
+ ds_put_format(ds, ") mac"ETH_ADDR_FMT"->"ETH_ADDR_FMT" type%04x "
+ "proto%"PRId8" tos%"PRIu8" ip"IP_FMT"->"IP_FMT" port%d->%d",
+ ETH_ADDR_ARGS(key->dl_src), ETH_ADDR_ARGS(key->dl_dst),
+ ntohs(key->dl_type), key->nw_proto, key->nw_tos,
+ IP_ARGS(&key->nw_src), IP_ARGS(&key->nw_dst),
+ ntohs(key->tp_src), ntohs(key->tp_dst));
+}
+
+int
+odp_action_len(uint16_t type)
+{
+ if (type > ODPAT_MAX) {
+ return -1;
+ }
+
+ switch ((enum odp_action_type) type) {
+ case ODPAT_OUTPUT: return 4;
+ case ODPAT_CONTROLLER: return 8;
+ case ODPAT_SET_DL_TCI: return 2;
+ case ODPAT_STRIP_VLAN: return 0;
+ case ODPAT_SET_DL_SRC: return ETH_ADDR_LEN;
+ case ODPAT_SET_DL_DST: return ETH_ADDR_LEN;
+ case ODPAT_SET_NW_SRC: return 4;
+ case ODPAT_SET_NW_DST: return 4;
+ case ODPAT_SET_NW_TOS: return 1;
+ case ODPAT_SET_TP_SRC: return 2;
+ case ODPAT_SET_TP_DST: return 2;
+ case ODPAT_SET_TUNNEL: return 8;
+ case ODPAT_SET_PRIORITY: return 4;
+ case ODPAT_POP_PRIORITY: return 0;
+ case ODPAT_DROP_SPOOFED_ARP: return 0;
+
+ case ODPAT_UNSPEC:
+ case __ODPAT_MAX:
+ return -1;
+ }
+
+ return -1;
+}
+
+static void
+format_generic_odp_action(struct ds *ds, const struct nlattr *a)