X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fdpif-netdev.c;h=1bb306ab12ae0b7a980a85ac83c25dc6c1ff86ca;hb=98403001ece61cbf783297c467a06032b200b8d0;hp=8aefaf9b0340fa45e1fb6ec792af096e2ccc4de7;hpb=d9065a90b6b955aa38586c952e8804ca7a22547e;p=sliver-openvswitch.git diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 8aefaf9b0..1bb306ab1 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -47,6 +47,7 @@ #include "ofpbuf.h" #include "packets.h" #include "poll-loop.h" +#include "random.h" #include "shash.h" #include "timeval.h" #include "util.h" @@ -297,10 +298,9 @@ dpif_netdev_destroy(struct dpif *dpif) } static int -dpif_netdev_get_stats(const struct dpif *dpif, struct ovs_dp_stats *stats) +dpif_netdev_get_stats(const struct dpif *dpif, struct dpif_dp_stats *stats) { struct dp_netdev *dp = get_dp_netdev(dpif); - memset(stats, 0, sizeof *stats); stats->n_flows = hmap_count(&dp->flow_table); stats->n_frags = dp->n_frags; stats->n_hit = dp->n_hit; @@ -336,7 +336,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type, int error; /* XXX reject devices already in some dp_netdev. */ - if (type[0] == '\0' || !strcmp(type, "system")) { + if (type[0] == '\0' || !strcmp(type, "system") || !strcmp(type, "dummy")) { internal = false; } else if (!strcmp(type, "internal")) { internal = true; @@ -378,8 +378,8 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type, port->netdev = netdev; port->internal = internal; - netdev_get_mtu(netdev, &mtu); - if (mtu != INT_MAX && mtu > max_mtu) { + error = netdev_get_mtu(netdev, &mtu); + if (!error) { max_mtu = mtu; } @@ -692,78 +692,10 @@ dpif_netdev_flow_get(const struct dpif *dpif, return 0; } -static int -dpif_netdev_validate_actions(const struct nlattr *actions, - size_t actions_len, bool *mutates) -{ - const struct nlattr *a; - unsigned int left; - - *mutates = false; - NL_ATTR_FOR_EACH (a, left, actions, actions_len) { - uint16_t type = nl_attr_type(a); - int len = odp_action_len(type); - - if (len != nl_attr_get_size(a)) { - return EINVAL; - } - - switch (type) { - case OVS_ACTION_ATTR_OUTPUT: - if (nl_attr_get_u32(a) >= MAX_PORTS) { - return EINVAL; - } - break; - - case OVS_ACTION_ATTR_USERSPACE: - break; - - case OVS_ACTION_ATTR_PUSH_VLAN: - *mutates = true; - if (nl_attr_get_be16(a) & htons(VLAN_CFI)) { - return EINVAL; - } - break; - - case OVS_ACTION_ATTR_SET_NW_TOS: - *mutates = true; - if (nl_attr_get_u8(a) & IP_ECN_MASK) { - return EINVAL; - } - break; - - case OVS_ACTION_ATTR_POP_VLAN: - case OVS_ACTION_ATTR_SET_DL_SRC: - case OVS_ACTION_ATTR_SET_DL_DST: - case OVS_ACTION_ATTR_SET_NW_SRC: - case OVS_ACTION_ATTR_SET_NW_DST: - case OVS_ACTION_ATTR_SET_TP_SRC: - case OVS_ACTION_ATTR_SET_TP_DST: - *mutates = true; - break; - - case OVS_ACTION_ATTR_SET_TUNNEL: - case OVS_ACTION_ATTR_SET_PRIORITY: - case OVS_ACTION_ATTR_POP_PRIORITY: - default: - return EOPNOTSUPP; - } - } - return 0; -} - static int set_flow_actions(struct dp_netdev_flow *flow, const struct nlattr *actions, size_t actions_len) { - bool mutates; - int error; - - error = dpif_netdev_validate_actions(actions, actions_len, &mutates); - if (error) { - return error; - } - flow->actions = xrealloc(flow->actions, actions_len); flow->actions_len = actions_len; memcpy(flow->actions, actions, actions_len); @@ -957,7 +889,6 @@ dpif_netdev_execute(struct dpif *dpif, { struct dp_netdev *dp = get_dp_netdev(dpif); struct ofpbuf copy; - bool mutates; struct flow key; int error; @@ -965,24 +896,10 @@ dpif_netdev_execute(struct dpif *dpif, return EINVAL; } - error = dpif_netdev_validate_actions(actions, actions_len, &mutates); - if (error) { - return error; - } - - if (mutates) { - /* We need a deep copy of 'packet' since we're going to modify its - * data. */ - ofpbuf_init(©, DP_NETDEV_HEADROOM + packet->size); - ofpbuf_reserve(©, DP_NETDEV_HEADROOM); - ofpbuf_put(©, packet->data, packet->size); - } else { - /* We still need a shallow copy of 'packet', even though we won't - * modify its data, because flow_extract() modifies packet->l2, etc. - * We could probably get away with modifying those but it's more polite - * if we don't. */ - copy = *packet; - } + /* Make a deep copy of 'packet', because we might modify its data. */ + ofpbuf_init(©, DP_NETDEV_HEADROOM + packet->size); + ofpbuf_reserve(©, DP_NETDEV_HEADROOM); + ofpbuf_put(©, packet->data, packet->size); flow_extract(©, 0, -1, &key); error = dpif_netdev_flow_from_nlattrs(key_attrs, key_len, &key); @@ -990,9 +907,8 @@ dpif_netdev_execute(struct dpif *dpif, error = dp_netdev_execute_actions(dp, ©, &key, actions, actions_len); } - if (mutates) { - ofpbuf_uninit(©); - } + + ofpbuf_uninit(©); return error; } @@ -1294,6 +1210,53 @@ dp_netdev_output_userspace(struct dp_netdev *dp, const struct ofpbuf *packet, return 0; } +static void +dp_netdev_sample(struct dp_netdev *dp, + struct ofpbuf *packet, struct flow *key, + const struct nlattr *action) +{ + const struct nlattr *subactions = NULL; + const struct nlattr *a; + size_t left; + + NL_NESTED_FOR_EACH_UNSAFE (a, left, action) { + int type = nl_attr_type(a); + + switch ((enum ovs_sample_attr) type) { + case OVS_SAMPLE_ATTR_PROBABILITY: + if (random_uint32() >= nl_attr_get_u32(a)) { + return; + } + break; + + case OVS_SAMPLE_ATTR_ACTIONS: + subactions = a; + break; + + case OVS_SAMPLE_ATTR_UNSPEC: + case __OVS_SAMPLE_ATTR_MAX: + default: + NOT_REACHED(); + } + } + + dp_netdev_execute_actions(dp, packet, key, nl_attr_get(subactions), + nl_attr_get_size(subactions)); +} + +static void +dp_netdev_action_userspace(struct dp_netdev *dp, + struct ofpbuf *packet, struct flow *key, + const struct nlattr *a) +{ + const struct nlattr *userdata_attr; + uint64_t userdata; + + userdata_attr = nl_attr_find_nested(a, OVS_USERSPACE_ATTR_USERDATA); + userdata = userdata_attr ? nl_attr_get_u64(userdata_attr) : 0; + dp_netdev_output_userspace(dp, packet, DPIF_UC_ACTION, key, userdata); +} + static int dp_netdev_execute_actions(struct dp_netdev *dp, struct ofpbuf *packet, struct flow *key, @@ -1304,14 +1267,15 @@ dp_netdev_execute_actions(struct dp_netdev *dp, unsigned int left; NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) { - switch (nl_attr_type(a)) { + int type = nl_attr_type(a); + + switch ((enum ovs_action_type) type) { case OVS_ACTION_ATTR_OUTPUT: dp_netdev_output_port(dp, packet, nl_attr_get_u32(a)); break; case OVS_ACTION_ATTR_USERSPACE: - dp_netdev_output_userspace(dp, packet, DPIF_UC_ACTION, - key, nl_attr_get_u64(a)); + dp_netdev_action_userspace(dp, packet, key, a); break; case OVS_ACTION_ATTR_PUSH_VLAN: @@ -1343,6 +1307,20 @@ dp_netdev_execute_actions(struct dp_netdev *dp, case OVS_ACTION_ATTR_SET_TP_DST: dp_netdev_set_tp_port(packet, key, a); break; + + case OVS_ACTION_ATTR_SAMPLE: + dp_netdev_sample(dp, packet, key, a); + break; + + case OVS_ACTION_ATTR_SET_TUNNEL: + case OVS_ACTION_ATTR_SET_PRIORITY: + case OVS_ACTION_ATTR_POP_PRIORITY: + /* not implemented */ + break; + + case OVS_ACTION_ATTR_UNSPEC: + case __OVS_ACTION_ATTR_MAX: + NOT_REACHED(); } } return 0; @@ -1364,6 +1342,7 @@ const struct dpif_class dpif_netdev_class = { dpif_netdev_port_query_by_number, dpif_netdev_port_query_by_name, dpif_netdev_get_max_ports, + NULL, /* port_get_pid */ dpif_netdev_port_dump_start, dpif_netdev_port_dump_next, dpif_netdev_port_dump_done, @@ -1379,8 +1358,6 @@ const struct dpif_class dpif_netdev_class = { dpif_netdev_execute, dpif_netdev_recv_get_mask, dpif_netdev_recv_set_mask, - NULL, /* get_sflow_probability */ - NULL, /* set_sflow_probability */ NULL, /* queue_to_priority */ dpif_netdev_recv, dpif_netdev_recv_wait,