diff options
| author | Ben Pfaff <blp@nicira.com> | 2010-12-10 10:40:58 -0800 |
|---|---|---|
| committer | Ben Pfaff <blp@nicira.com> | 2010-12-10 11:13:32 -0800 |
| commit | cdee00fd635d1e0f1eeb5d9c009daeb59abd4777 (patch) | |
| tree | 49ef94d30bcb995fa1070c3aa770a9a515b26b0a /lib/odp-util.c | |
| parent | 7f8ca6459c37ede8faf13f730bcd4d9f05dfd13b (diff) | |
| download | openvswitch-cdee00fd635d1e0f1eeb5d9c009daeb59abd4777.tar.gz | |
datapath: Replace "struct odp_action" by Netlink attributes.
In the medium term, we plan to migrate the datapath to use Netlink as its
communication channel. In the short term, we need to be able to have
actions with 64-bit arguments but "struct odp_action" only has room for
48 bits. So this patch shifts to variable-length arguments using Netlink
attributes, which starts in on the Netlink transition and makes 64-bit
arguments possible at the same time.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
Diffstat (limited to 'lib/odp-util.c')
| -rw-r--r-- | lib/odp-util.c | 141 |
1 files changed, 98 insertions, 43 deletions
diff --git a/lib/odp-util.c b/lib/odp-util.c index 6b4f5fada..2ed551d2a 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -19,26 +19,15 @@ #include <inttypes.h> #include <stdlib.h> #include <string.h> +#include "byte-order.h" #include "coverage.h" #include "dynamic-string.h" #include "flow.h" +#include "netlink.h" #include "packets.h" #include "timeval.h" #include "util.h" -union odp_action * -odp_actions_add(struct odp_actions *actions, uint16_t type) -{ - union odp_action *a; - size_t idx; - - idx = actions->n_actions++ & (MAX_ODP_ACTIONS - 1); - a = &actions->actions[idx]; - memset(a, 0, sizeof *a); - a->type = type; - return a; -} - void format_odp_flow_key(struct ds *ds, const struct odp_flow_key *key) { @@ -59,54 +48,114 @@ format_odp_flow_key(struct ds *ds, const struct odp_flow_key *key) 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 4; + 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 4; + 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) +{ + ds_put_format(ds, "action%"PRId16, nl_attr_type(a)); + if (a->nla_len) { + const uint8_t *unspec; + unsigned int i; + + unspec = nl_attr_get(a); + for (i = 0; i < a->nla_len; i++) { + ds_put_char(ds, i ? ' ': '('); + ds_put_format(ds, "%02x", unspec[i]); + } + ds_put_char(ds, ')'); + } +} + void -format_odp_action(struct ds *ds, const union odp_action *a) +format_odp_action(struct ds *ds, const struct nlattr *a) { - switch (a->type) { + const uint8_t *eth; + ovs_be32 ip; + + if (nl_attr_get_size(a) != odp_action_len(a->nla_len)) { + ds_put_format(ds, "***bad action: length is %zu, expected %d*** ", + nl_attr_get_size(a), odp_action_len(a->nla_len)); + format_generic_odp_action(ds, a); + return; + } + + switch (nl_attr_type(a)) { case ODPAT_OUTPUT: - ds_put_format(ds, "%"PRIu16, a->output.port); + ds_put_format(ds, "%"PRIu16, nl_attr_get_u32(a)); break; case ODPAT_CONTROLLER: - ds_put_format(ds, "ctl(%"PRIu32")", a->controller.arg); + ds_put_format(ds, "ctl(%"PRIu32")", nl_attr_get_u32(a)); break; case ODPAT_SET_TUNNEL: - ds_put_format(ds, "set_tunnel(%#"PRIx32")", ntohl(a->tunnel.tun_id)); + ds_put_format(ds, "set_tunnel(%#"PRIx32")", + ntohl(nl_attr_get_be32(a))); break; case ODPAT_SET_DL_TCI: ds_put_format(ds, "set_tci(vid=%"PRIu16",pcp=%d)", - vlan_tci_to_vid(a->dl_tci.tci), - vlan_tci_to_pcp(a->dl_tci.tci)); + vlan_tci_to_vid(nl_attr_get_be16(a)), + vlan_tci_to_pcp(nl_attr_get_be16(a))); break; case ODPAT_STRIP_VLAN: ds_put_format(ds, "strip_vlan"); break; case ODPAT_SET_DL_SRC: - ds_put_format(ds, "set_dl_src("ETH_ADDR_FMT")", - ETH_ADDR_ARGS(a->dl_addr.dl_addr)); + eth = nl_attr_get_unspec(a, ETH_ADDR_LEN); + ds_put_format(ds, "set_dl_src("ETH_ADDR_FMT")", ETH_ADDR_ARGS(eth)); break; case ODPAT_SET_DL_DST: - ds_put_format(ds, "set_dl_dst("ETH_ADDR_FMT")", - ETH_ADDR_ARGS(a->dl_addr.dl_addr)); + eth = nl_attr_get_unspec(a, ETH_ADDR_LEN); + ds_put_format(ds, "set_dl_dst("ETH_ADDR_FMT")", ETH_ADDR_ARGS(eth)); break; case ODPAT_SET_NW_SRC: - ds_put_format(ds, "set_nw_src("IP_FMT")", - IP_ARGS(&a->nw_addr.nw_addr)); + ip = nl_attr_get_be32(a); + ds_put_format(ds, "set_nw_src("IP_FMT")", IP_ARGS(&ip)); break; case ODPAT_SET_NW_DST: - ds_put_format(ds, "set_nw_dst("IP_FMT")", - IP_ARGS(&a->nw_addr.nw_addr)); + ip = nl_attr_get_be32(a); + ds_put_format(ds, "set_nw_dst("IP_FMT")", IP_ARGS(&ip)); break; case ODPAT_SET_NW_TOS: - ds_put_format(ds, "set_nw_tos(%"PRIu8")", a->nw_tos.nw_tos); + ds_put_format(ds, "set_nw_tos(%"PRIu8")", nl_attr_get_u8(a)); break; case ODPAT_SET_TP_SRC: - ds_put_format(ds, "set_tp_src(%"PRIu16")", ntohs(a->tp_port.tp_port)); + ds_put_format(ds, "set_tp_src(%"PRIu16")", ntohs(nl_attr_get_be16(a))); break; case ODPAT_SET_TP_DST: - ds_put_format(ds, "set_tp_dst(%"PRIu16")", ntohs(a->tp_port.tp_port)); + ds_put_format(ds, "set_tp_dst(%"PRIu16")", ntohs(nl_attr_get_be16(a))); break; case ODPAT_SET_PRIORITY: - ds_put_format(ds, "set_priority(0x%"PRIx32")", a->priority.priority); + ds_put_format(ds, "set_priority(%#"PRIx32")", nl_attr_get_u32(a)); break; case ODPAT_POP_PRIORITY: ds_put_cstr(ds, "pop_priority"); @@ -115,23 +164,29 @@ format_odp_action(struct ds *ds, const union odp_action *a) ds_put_cstr(ds, "drop_spoofed_arp"); break; default: - ds_put_format(ds, "***bad action 0x%"PRIx16"***", a->type); + format_generic_odp_action(ds, a); break; } } void -format_odp_actions(struct ds *ds, const union odp_action *actions, - size_t n_actions) +format_odp_actions(struct ds *ds, const struct nlattr *actions, + unsigned int actions_len) { - size_t i; - for (i = 0; i < n_actions; i++) { - if (i) { - ds_put_char(ds, ','); + if (actions_len) { + const struct nlattr *a; + unsigned int left; + + NL_ATTR_FOR_EACH (a, left, actions, actions_len) { + if (a != actions) { + ds_put_char(ds, ','); + } + format_odp_action(ds, a); } - format_odp_action(ds, &actions[i]); - } - if (!n_actions) { + if (left) { + ds_put_format(ds, " ***%u leftover bytes***", left); + } + } else { ds_put_cstr(ds, "drop"); } } @@ -157,7 +212,7 @@ format_odp_flow(struct ds *ds, const struct odp_flow *f) ds_put_cstr(ds, ", "); format_odp_flow_stats(ds, &f->stats); ds_put_cstr(ds, ", actions:"); - format_odp_actions(ds, f->actions, f->n_actions); + format_odp_actions(ds, f->actions, f->actions_len); } void |
